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

如何正确克隆JavaScript对象?


当前回答

有很多答案,但没有一个提到ECMAScript 5中的Object.create,它确实没有给您一个确切的副本,而是将源设置为新对象的原型。

因此,这不是问题的确切答案,但它是一个单行解决方案,因此很优雅。它最适合2种情况:

在这种继承有用的地方(duh!)源对象不会被修改,因此这两个对象之间的关系不成问题。

例子:

var foo = { a : 1 };
var bar = Object.create(foo);
foo.a; // 1
bar.a; // 1
foo.a = 2;
bar.a; // 2 - prototype changed
bar.a = 3;
foo.a; // Still 2, since setting bar.a makes it an "own" property

为什么我认为这种解决方案更优越?它是本地的,因此没有循环,没有递归。然而,较旧的浏览器将需要polyfill。

其他回答

好的,我知道它有很多答案,但没有人指出,EcmaScript5有赋值方法,在FF和Chrome上工作,它复制可枚举的,并且拥有财产和符号。

对象指定(Object Assign)

如果您正在使用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;
}

在ES-6中,您可以简单地使用Object.assign(…)。前任:

let obj = {person: 'Thor Odinson'};
let clone = Object.assign({}, obj);

这里有一个很好的参考:https://googlechrome.github.io/samples/object-assign-es6/

2020年7月6日更新

有三(3)种方法可以在JavaScript中克隆对象。由于JavaScript中的对象是引用值,因此不能简单地使用=进行复制。

方法如下:

const food = { food: 'apple', drink: 'milk' }


// 1. Using the "Spread"
// ------------------

{ ...food }


// 2. Using "Object.assign"
// ------------------

Object.assign({}, food)


// 3. "JSON"
// ------------------

JSON.parse(JSON.stringify(food))

// RESULT:
// { food: 'apple', drink: 'milk' }

这可以用作参考摘要。

对于深度复制和克隆,JSON.stringify然后JSON.parse对象:

obj = { a: 0 , b: { c: 0}};
let deepClone = JSON.parse(JSON.stringify(obj));
obj.a = 5;
obj.b.c = 5;
console.log(JSON.stringify(deepClone)); // { a: 0, b: { c: 0}}