我希望了解将对象推入数组时的以下行为。
(1)我创建一个对象,创建该对象的属性,然后将其推入数组。
var array = [];
var obj = {};
obj.x = 1;
array.push(obj);
console.log(array); //Output [{x: 1}]
考虑两种选择:
(2a):我更改了对象的属性,因此更改了数组中引用的对象:
obj.x = 2;
console.log(array); //Output [{x: 2}] ... it has been changed
(2b 代替2a )我使对象引用引用一个新对象并创建该属性,数组中引用的原始对象未更改:
obj = {}; //Change reference to new object
obj.x = 2;
console.log(array); //Output [{x: 1}] ... it is unchanged
为什么会这样?
P.S::我注意到这里讨论了这种区别(https://docs.microsoft.com/en-us/aspnet/signalr/),但是并没有令人满意地解释它。
答案 0 :(得分:0)
JavaScript对象通过对象引用被推送到数组上,也就是说,如果您将对象推送到数组中,然后再操作该对象,则数组的内容也会发生变化,因为数组引用了同一对象。
通过初始化或克隆步骤创建新对象可以解决此问题,在数组中有两个完全不同的对象。
这样想:当您在对象上调用push
时,对象本身不会进入数组,而对对象的引用(指针)则会出现。像数字这样的原始类型会被复制,而对象则不会。
答案 1 :(得分:0)
在推动对象时,添加了第一个对象的引用,因此这就是将其更新为2的原因。
您正在创建新对象并分配给obj,并且更改该对象不会更改数组值,因为它指向的是其他引用。
答案 2 :(得分:0)
我不知道我欠佳的ASCII绘图技能是否会有所帮助,但这是一种尝试:
-----------------------------------------
(1)
-----------------------------------------
array = []
[ ] 'array'
^--------/
obj = {}
[ ] 'array' { } 'obj'
^--------/ ^-------/
obj.x = 1
[ ] 'array' {x: 1} 'obj'
^--------/ ^---------/
array.push(obj)
,-----------------v
[0: * ] 'array' {x: 1} 'obj'
^------------/ ^---------/
-----------------------------------------
(2a)
-----------------------------------------
obj.x = 2
,-----------------v
[0: * ] 'array' {x: 2} 'obj'
^------------/ ^---------/
-----------------------------------------
(2b)
-----------------------------------------
obj = {}
,-----------------v
[0: * ] 'array' {x: 1} 'obj' { }
^------------/ `-------^
obj.x = 2
,-----------------v
[0: * ] 'array' {x: 1} 'obj' {x: 2}
^------------/ `--------^