如何在JavaScript中创建不影响该对象其他实例的对象的实例,这是一个示例:
var A = {
b: "2",
c: "3",
d: {
e: "5",
f:{
g: "7"
},
h: function(){
return "8";
}
}
}
var a1 = Object.create(A);
var a2 = Object.create(A);
a1.d.f.g = 10;
console.log(a2.d.f.g);//Result is 10 while it was supposed to be 7
在上面的示例中,当a1.d.f.g
被更改时,a2.d.f.g
也被更改了。怎么了?
我什至尝试了Object.assign({}, A)
,但问题仍然存在。
var a1 = Object.assign({}, A);
var a2 = Object.assign({}, A);
更新:
由于有了一些提供给我线索的答案,经过大量搜索后,我发现JavaScript中有两个与对象复制有关的概念,Shallow Copy
和Deep Copy
,在浅表复制中,仅复制了顶级属性但是如果要拥有一个完全独立的实例,则需要深度复制或深度克隆。
浅表副本成功复制了数字和字符串之类的原始类型,但是不会递归地复制任何对象引用,而是新复制的对象将引用同一对象。
如果一个对象引用了其他对象,则在执行该对象的浅表复制时,会将引用复制到外部对象。
执行深度复制时,这些外部对象也会被复制,因此新的克隆对象与旧对象完全独立。 Source
我个人认为JavaScript的浅层复制和深层复制概念似乎很奇怪,没有意义,但这是事实,此外,C#中也存在similar stuff。 Object.assign()
和spread operator
进行浅表复制,因此您需要另一个函数来为您进行深表克隆。
有人建议使用JSON.parse(JSON.stringify(obj))
,但不适用于本身具有功能的属性,例如,如果您使用JSON解决方案,则以上示例中的a1.d.h()
无效,而且类型可能会更改在某些情况下,例如Date类型。
建议使用某些库,但就我而言,我不想使用任何第三方。我发现最好使用遍历引用对象属性的循环并创建一个深层克隆,这是我正在谈论的方法:
function deepClone (obj) {
var _out = new obj.constructor;
var getType = function (n) {
return Object.prototype.toString.call(n).slice(8, -1);
}
for (var _key in obj) {
if (obj.hasOwnProperty(_key)) {
_out[_key] = getType(obj[_key]) === 'Object' || getType(obj[_key]) === 'Array' ? deepClone(obj[_key]) : obj[_key];
}
}
return _out;
}
所以最终它将变成这样:
var a1 = deepClone(A);
var a2 = deepClone(A);
a1.d.f.g = 10;
console.log(a2.d.f.g);//Result is 7 now
答案 0 :(得分:1)
您需要创建一个深克隆,可以使用JSON.parse(JSON.stringify())
进行深克隆
var A = {
b: "2",
c: "3",
d: {
e: "5",
f:{
g: "7"
}
}
}
var a1 = JSON.parse(JSON.stringify(A));
var a2 = JSON.parse(JSON.stringify(A));
a1.d.f.g = 10;
console.log(a2.d.f.g);