我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。

如何正确克隆JavaScript对象?


当前回答

我在复制对象时遇到问题。这是因为,当您执行以下操作时,您只对对象进行了“引用”,而当稍后更新源对象值时,克隆的复制对象也会更改值,因为它只是一个“引用”。因此,您可以看到源对象上次更改的多个值。

let x = { a: 1 };
let y = x; // y is a reference to x, so if x changes y also changes and v/v

因此,要解决这个问题,请执行以下操作:

let y = JSON.parse(JSON.stringify(x)); //see Note below

防止引用的另一种方法是执行以下操作:

let x = { a: 1 };
let y = Object.assign({}, x); // Object.assign(target, ...sources)

y.a = 2;
console.log(x); // { a: 1 }
console.log(y); // { a: 2 }

注:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#warning_for_deep_clone

其他回答

对于使用AngularJS的用户,也可以直接克隆或扩展此库中的对象。

var destination = angular.copy(source);

or

angular.copy(source, destination);

更多关于angular.copy文档。。。

如果您正在使用TypeScript,需要支持较旧的web浏览器(因此无法使用Object.assign),并且没有使用内置有克隆方法的库,那么您可以在几行代码中使自己成为组合助手。它结合了对象,如果只有一个,就克隆它。

/** Creates a new object that combines the properties of the specified objects. */
function combine(...objs: {}[]) {
    const combined = {};
    objs.forEach(o => Object.keys(o).forEach(p => combined[p] = o[p]));
    return combined;
}
function clone(obj) {
    if(obj == null || typeof(obj) != 'object')
        return obj;    
    var temp = new obj.constructor(); 
    for(var key in obj)
        temp[key] = clone(obj[key]);    
    return temp;
}
var x = {'e': 2, 'd': 8, 'b': 5};

const y = {};
for(let key in x) {
    y[key] = x[key];
}
console.log(y); // =>>> {e: 2, d: 8, b: 5}

const z = {};
Object.keys(x).forEach(key => {
    z[key] = x[key];
});
console.log(z); // =>>> {e: 2, d: 8, b: 5}

const w = {};
for(let i = 0; i < Object.keys(x).length; i++) {
    w[Object.keys(x)[i]] = x[Object.keys(x)[i]];
}
console.log(w); // =>>> {e: 2, d: 8, b: 5}

const v = {};
for(let key of Object.keys(x)) {
    v[key] = x[key];
}
console.log(v); // =>>> {e: 2, d: 8, b: 5}

x['q'] = 100;   // Altering x will not affect the other objects

console.log(x); // =>>> {e: 2, d: 8, b: 5, q: 100}
console.log(y); // =>>> {e: 2, d: 8, b: 5}
console.log(z); // =>>> {e: 2, d: 8, b: 5}
console.log(w); // =>>> {e: 2, d: 8, b: 5}
console.log(v); // =>>> {e: 2, d: 8, b: 5}

好的,假设你有下面的这个对象,你想克隆它:

let obj = {a:1, b:2, c:3}; //ES6

or

var obj = {a:1, b:2, c:3}; //ES5

答案主要取决于您使用的ECMAscript,在ES6+中,您可以简单地使用Object.assign来执行克隆:

let cloned = Object.assign({}, obj); //new {a:1, b:2, c:3};

或使用如下扩展运算符:

let cloned = {...obj}; //new {a:1, b:2, c:3};

但是如果你使用ES5,你可以使用很少的方法,但JSON.stringify,只需确保你没有使用大量数据来复制,但在很多情况下,这可能是一种简单的方法,比如:

let cloned = JSON.parse(JSON.stringify(obj)); 
//new {a:1, b:2, c:3};, can be handy, but avoid using on big chunk of data over and over