Javascript对象分配'他奇怪的行为
Javascript object assignment's strange behavior
我是javascript的新手(实际上是编程的新手)。我遇到了for/in循环的这种行为,我不太理解。以下几段代码是使用控制台中的$node命令运行的。
code_0:
var result = {};
var list = ['A', 'B', 'C'];
for(var index in list){
var id = list[index];
result[id] = {};
result[id]['name'] = id;
}
console.log(result);
结果_0:
{ A: { name: 'A' }, B: { name: 'B' }, C: { name: 'C' } }
code_1:
var result = {};
var list = ['A', 'B', 'C'];
var INIT = {'a': 0, 'b': 0, 'c': 0,}
for(var index in list){
var id = list[index];
result[id] = INIT;
result[id]['name'] = id;
}
console.log(result);
结果1:
{ A: { a: 0, b: 0, c: 0, name: 'C' },
B: { a: 0, b: 0, c: 0, name: 'C' },
C: { a: 0, b: 0, c: 0, name: 'C' } }
我能理解为什么code_0会给出result_0。但结果_1是我不明白的。我预计结果_1为:
{ A: { a: 0, b: 0, c: 0, name: 'A' },
B: { a: 0, b: 0, c: 0, name: 'B' },
C: { a: 0, b: 0, c: 0, name: 'C' } }
code_0和code_1之间有什么区别?为什么code_1会给出result_1?
编辑:*添加与问题相关的标签。*更改标题。(标题过去是关于循环的)
对象在Javascript中是通过引用(而不是复制)分配的。这是在第一次学习Javascript时混淆和学习的一个常见点。
在您的code_1
块中,这行代码:
result[id] = INIT;
是在循环的每次迭代中为完全相同的对象指定一个引用,因此它们都指向相同的对象,并且都具有相同的属性(因为它们都是相同的对象)。因此,对result[id]
的任何进一步更改实际上都只是对INIT的更改,INIT是result
中所有插槽正在使用的同一对象,因此它们看起来都同时更改。
在Javascript中,如果您希望在每次分配中都有一个对象的单独副本,那么您必须在分配之前创建一个新对象。在最新的浏览器中,可以使用Object.assign()
将可枚举属性从一个对象复制到另一个对象。
使用Object.assign()
,有一种方法可以解决在分配对象之前复制对象的问题:
var result = {};
var list = ['A', 'B', 'C'];
var INIT = {'a': 0, 'b': 0, 'c': 0,}
for(var index in list){
var id = list[index];
// make a new object that is a copy of INIT
var obj = Object.assign({}, INIT);
obj.name = id;
// put that new object into result[id]
result[id] = obj;
}
console.log(result);
对于较旧的浏览器,这里有一个适用于Object.assign()
的polyfill:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
这里有一个简单的例子:
var items = {a:1, b:2, c:3};
var list1 = items;
var list2 = items;
list1.a = 10;
console.log(items); // {a:10, b:2, c:3}
console.log(list1); // {a:10, b:2, c:3}
console.log(list2); // {a:10, b:2, c:3}
console.log(list1 === items); // true, they are the same object
console.log(list2 === items); // true, they are the same object
您可以看到,所有三个变量都显示相同的值,因为它们都指向完全相同的对象,因此通过三个变量中的任何一个修改对象都会产生完全相同的变化。
- 为什么在Javascript中将一个对象分配给另一个变量也会更改初始对象
- 在运行时使用预先确定的对象分配变量
- Javascript对象分配gottcha
- 通过程序将对象分配给数组
- AngularJS-对象分配不起作用
- 在PHP中为JSON对象分配标识符/名称
- 对象分配在此angularjs控制器中不起作用
- 对象分配 - 更新特定属性
- 将对象分配给另一个对象并保留原始数据
- ES6 对象分配部分项
- 为每个对象分配一个键
- 将函数中的对象分配给变量或调用 setState 没有这个
- 按对象数组中的值为对象分配等级
- 为什么将其他对象分配给内置对象(例如文档、窗口)没有意义
- 将FileReader内部的结果对象分配给变量
- 为Javascript对象分配函数
- Javascript对象分配'他奇怪的行为
- 了解在 JavaScript 中为对象分配函数
- 为CanvasXpress的Json对象分配Javascript数组值
- 只需使用Immutable.js将对象分配给变量,即可克隆新对象