简体   繁体   English

JavaScript对象分配的奇怪行为

[英]Javascript object assignment's strange behavior

I am new to javascript (new to programming overall, really). 我是javascript新手(真的是整体编程新手)。 And I encountered this behavior of for/in loop that I don't quite understand. 我遇到了我不太了解的for / in循环行为。 The following pieces of code were run with $node command in console. 以下代码段在控制台中使用$ node命令运行。

code_0: 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);

result_0: RESULT_0:

{ A: { name: 'A' }, B: { name: 'B' }, C: { name: 'C' } }

code_1: 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);

result_1: 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' } }

I can understand why code_0 would give result_0. 我能理解为什么code_0会给出result_0。 But result_1 is what I don't understand. 但是result_1是我不理解的。 I expected result_1 to be: 我期望result_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' } }

What's the difference between code_0 and code_1? code_0和code_1有什么区别? Why would code_1 give result_1? 为什么code_1给出result_1?

EDIT: * Add tags related to the question. 编辑:*添加与问题相关的标签。 * Change title. *更改标题。 (Title used to be about for/in loops) (标题过去大约是for / in循环)

Objects are assigned by reference (not by copy) in Javascript. 对象是通过Javascript中的引用(而不是副本)分配的。 This is a common point of confusing and learning when first getting up to speed in Javascript. 当初次使用Javascript时,这是令人困惑和学习的共同点。

In your code_1 block, this line of code: 在您的code_1块中,以下代码行:

result[id] = INIT;

is assigning a reference to the exact same object in every iteration of your loop, thus they all point to the same object and will all have the same properties (since they are all the same object). 在循环的每次迭代中都为完全相同的对象分配了一个引用,因此它们都指向同一对象,并且都具有相同的属性(因为它们都是相同的对象)。 So, any further changes to result[id] are really just changes to INIT which is the same object that all the slots in result are using so they all appear to change at once. 因此,对result[id]任何进一步更改实际上只是对INIT的更改,INIT是result中所有插槽所使用的同一对象,因此它们似乎都在立即更改。

In Javascript, if you want a separate copy of an object in each assignment, then you have to create a new object before assigning. 在Javascript中,如果要在每个分配中单独复制一个对象,则必须在分配之前创建一个新对象。 In the latest browsers, you can use Object.assign() to copy enumerable properties from one object to another. 在最新的浏览器中,可以使用Object.assign()将可枚举的属性从一个对象复制到另一个对象。

Using Object.assign() , here's one way around the issue that makes a copy of the object before assigning it: 使用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);

For older browsers, there's a polyfill for Object.assign() here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign 对于较旧的浏览器,这里有一个Object.assign()https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


Here's a little simpler example: 这是一个更简单的示例:

 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

You can see that all three variables show the same values because they all point to the exact same object so modifying the object via any one of the three variables make the exact same change. 您会看到所有三个变量都显示相同的值,因为它们都指向完全相同的对象,因此通过三个变量中的任何一个修改对象都会产生完全相同的更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM