如何在JavaScript中创建对象的完全独立的实例

时间:2019-07-13 05:20:52

标签: javascript

如何在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 CopyDeep Copy,在浅表复制中,仅复制了顶级属性但是如果要拥有一个完全独立的实例,则需要深度复制或深度克隆。

  

浅表副本成功复制了数字和字符串之类的原始类型,但是不会递归地复制任何对象引用,而是新复制的对象将引用同一对象。

     

如果一个对象引用了其他对象,则在执行该对象的浅表复制时,会将引用复制到外部对象。

     

执行深度复制时,这些外部对象也会被复制,因此新的克隆对象与旧对象完全独立。   Source

我个人认为JavaScript的浅层复制和深层复制概念似乎很奇怪,没有意义,但这是事实,此外,C#中也存在similar stuffObject.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

1 个答案:

答案 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);