2016-11-05 57 views
1

有没有办法让下面的浅拷贝只得到一层深?我有一种方法可以使用完全不同的设计来解决此问题,但我想知道是否有其他人遇到过我想要转换为字符串的内容。JavaScript:将一个循环引用对象的浅拷贝字符串化?

var SomeObjClass = function() { 
    var self = this; 
    this.group = { 
     members: [self] 
    }; 
}; 
var p = new SomeObjClass(); 
var str = JSON.stringify(p); 
+0

错误?将圆形结构转换为JSON – Mahi

+0

您能提供一个预期结果的例子吗? –

+1

没有什么可以复制的。做一个浅层克隆就像重新调用你的构造函数来创建一个新对象一样。我假设还有其他代码没有粘贴。 –

回答

2

这是一个有点不清楚你在问什么,但如果你的目标是简单的字符串化一个圆形对象,你就必须重写toJSON指定您希望如何处理你的对象,以表示

function SomeObjClass() { 
 
    var self = this; 
 
    this.group = { 
 
    members: [self] 
 
    }; 
 
} 
 

 
SomeObjClass.prototype.addMember = function(m) { 
 
    this.group.members.push(m); 
 
}; 
 

 
// when stringifying this object, don't include `self` in group.members 
 
SomeObjClass.prototype.toJSON = function() { 
 
    var self = this; 
 
    return { 
 
    group: { 
 
     members: self.group.members.filter(function (x) { 
 
     return x !== self 
 
     }) 
 
    } 
 
    }; 
 
} 
 

 
var a = new SomeObjClass(); 
 
var b = new SomeObjClass(); 
 
a.addMember(b); 
 

 
console.log(JSON.stringify(a))

这可能是最好的,我可以帮你没有看到更多的代码。我不知道你是如何使用这段代码的,但无论如何,这可能不是你班上最好的设计。如果你分享课程的其余部分和使用它的代码,我们可以更有效地帮助你。

+0

这是一种解决方法,但我想知道是否在调用JSON时可以修改特定参数以执行我所要求的“浅层克隆”,但在这种情况下,您将覆盖原有内容。我会赞成这一点,可能会忽略这种设计模式,并考虑其他方式。这篇文章的全部原因是因为虽然循环引用在客户端很好,但是当尝试执行诸如通过网络将数据从一个客户端发送到另一个客户端时,由于循环引用的缘故,堆栈溢出是随之而来的。 – simon

0

如果您检查关于JSON.stringify的MDN参考,您会看到它接受作为第二个参数的replacer函数。此功能对于按需处理需要字符串化的元素非常有用。

它可以帮助您避免您的循环问题。

例如:

function avoidCircularReference(obj) { 
 
    return function(key, value) { 
 
    return key && typeof value === 'object' && obj === value ? undefined : value; 
 
    }; 
 
} 
 

 
var SomeObjClass = function() { 
 
    var self = this; 
 
    this.group = { 
 
     members: [self, {a:'f', b: [self]}] 
 
    }; 
 
}; 
 
var p = new SomeObjClass(); 
 
var str = JSON.stringify(p, avoidCircularReference(p)); 
 
console.log(str);

然而,如文档中所述及所示运行示例:

注意:您不能使用替代品的功能删除数组中的值。如果您返回未定义或函数,则使用null。

所以你必须以某种方式处理这些空值。无论如何,你可以玩这个功能,并“适应”你的需求。举例来说,并应用到你的例子:

function avoidCircularReference(obj) { 
 
    var removeMeFromArray = function(arr) { 
 
    var index = arr.indexOf(obj); 
 
    if (index > -1) { 
 
     arr.splice(index, 1); 
 
    } 
 
    }; 
 

 
    return function(key, value) { 
 
    if (Object.prototype.toString.call(value) === "[object Array]") { 
 
     removeMeFromArray(value); 
 
    } 
 
    return value; 
 
    }; 
 
} 
 

 
var SomeObjClass = function() { 
 
    var self = this; 
 
    this.group = { 
 
    members: [self, { 
 
     a: 'f', 
 
     b: [self] 
 
    }] 
 
    }; 
 
}; 
 
var p = new SomeObjClass(); 
 
var str = JSON.stringify(p, avoidCircularReference(p)); 
 
console.log(str);

0

为了解决这个问题,并保持JSON.stringify简单起见,我用下面的办法(在这里我的脱水法)

public dehydrate(): string { 
    var seenObjects = []; 
    function inspectElement(key, value) { 
     if (detectCycle(value)) { 
      return '[Ciclical]'; 
     } else { 
      return value; 
     }; 
    }; 
    function detectCycle(obj): boolean { 
     if (obj && (typeof obj == 'object')) { 
      for (let r of seenObjects) { 
       if (r == obj) { 
        return true; 
       }; 
      }; 
      seenObjects.push(obj); 
     }; 
     return false; 
    }; 
    let json: string = JSON.stringify(this, inspectElement,' '); 
    return json; 
}; 

请注意,尽管这是TypeScript,但使用强类型实现方法内的结果会导致我们产生一些混淆。

不幸的是,我不得不使用for而不是数组搜索,因为它根本不适用于我。