[英]'Object.assign' mutates state in deeper levels
I have a sample JSBin code at http://jsbin.com/givolafala/edit?html,js,console,output 我在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);
In this example, I'm changing the name which is at the top level from John
to Mathew
. 在这个例子中,我正在改变从John
到Mathew
的顶级名称 。 The Object.assign
returns the new state with the new name Mathew
. Object.assign
返回新名称Mathew
的新状态。 The oldObject
keeps its previous value John
. oldObject
保留其先前值John
。
If I change any value in any level other than the root, it does not work. 如果我更改除root之外的任何级别中的任何值,则它不起作用。 In the example I change the city to los angeles
, and you will notice that the newObject
and the oldObject
have the same city los angeles
. 在示例中,我将城市更改为los angeles
,您会注意到newObject
和oldObject
具有相同的城市los angeles
。 So the oldObject
state is mutated. 因此oldObject
状态发生了变异。
Is this a bug? 这是一个错误吗?
This is not a bug, this is called reference. 这不是一个bug,这叫做引用。 There's a difference between how primitive values and objects (references to objectes actually) behaves. 原始值和对象(实际上是对象的引用)的行为方式之间存在差异。
var oldObject = { name: 'John', address: { city: 'new york'}};
oldObject
consist of: oldObject
包括:
name
which is a string value (primitive) name
是一个字符串值 (原始) addres
which is an object, so oldObject
really has a reference to address
object addres
这是一个对象,所以oldObject
真的有一个引用 address
对象 Now: 现在:
var newObject = Object.assign({}, oldObject);
After copying newObject
also has name
value and address
reference 复制newObject
还具有name
值和address
引用
newObject.name = 'Mathew';
Here you change a value of newObject
's property. 在这里,您可以更改newObject
属性的值。
newObject.address.city = 'los angeles';
But here you change a property of an object that newObject
references . 但是在这里你改变了newObject
引用的对象的属性。 But this reference is also in oldObject
so this will change oldObject
too. 但是这个引用也在oldObject
所以这也会改变oldObject
。
Basically both newObject
and oldObject
have a reference to same same address
object . 基本上newObject
和oldObject
都引用了相同的address
对象 。
What you expected to achieve is called deep copy . 您期望实现的目标称为深层复制 。
I guess the description of Object.assign()
says everything: 我想Object.assign()
的描述说明了一切:
The Object.assign() method only copies enumerable and own properties from a source object to a target object. Object.assign()方法仅将可枚举和自己的属性从源对象复制到目标对象。
It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters . 它在源上使用[[Get]],在目标上使用[[Set]],因此它将调用getter和setter 。Therefore it assigns properties versus just copying or defining new properties. 因此,它分配属性而不仅仅是复制或定义新属性。 This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters. 如果合并源包含getter,这可能使它不适合将新属性合并到原型中。 For copying property definitions, including their enumerability, into prototypes Object.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead. 为了将属性定义(包括它们的可枚举性)复制到原型中,应该使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.