我在http://jsbin.com/givolafala/edit?html,js,console,output
有一个示例JSBin代码
var oldObject = { name: 'John', address: { city: 'new york'}};
var newObject = Object.assign({}, oldObject);
console.log(oldObject);
console.log(newObject);
newObject.name = 'Mathew';
newObject.address.city = 'los angeles';
console.log(oldObject);
console.log(newObject);
在此示例中,我正在更改位于John
到Mathew
顶级的名称。 Object.assign
以新名称Mathew
返回新状态。 oldObject
保留其先前值John
。
如果我更改除root之外的任何级别中的任何值,则它不起作用。在示例中,我将城市更改为los angeles
,您会注意到newObject
和oldObject
具有相同的城市los angeles
。所以oldObject
状态发生了变异。
这是一个错误吗?
答案 0 :(得分:4)
这不是错误,这称为引用。原始值和对象(实际上对象的行为)的行为方式之间存在差异。
var oldObject = { name: 'John', address: { city: 'new york'}};
oldObject
包括:
name
这是一个字符串值(原始)addres
这是一个对象,因此oldObject
确实有一个引用到address
对象现在:
var newObject = Object.assign({}, oldObject);
复制后newObject
还有name
值和address
参考
newObject.name = 'Mathew';
您可以在此处更改newObject
属性的值。
newObject.address.city = 'los angeles';
但是,您可以在此处更改newObject
引用的对象的属性。但是这个引用也在oldObject
中,所以这也会改变oldObject
。
基本上,newObject
和oldObject
都有对同一个address
对象的引用。
您期望实现的目标称为深层复制。
答案 1 :(得分:2)
我想Object.assign()
的描述说明了一切:
Object.assign()方法仅将源对象的可枚举和自有属性复制到目标对象。
它在源上使用[[Get]],在目标上使用[[Set]],因此它将调用getter和setter 。因此,它会分配属性而不仅仅是复制或定义新属性。如果合并源包含getter,这可能会使它不适合将新属性合并到原型中。要将属性定义(包括其可枚举性)复制到原型中,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty()。