为什么更改属性的值会更改数组中所有相似命名的属性的值?

时间:2018-06-23 03:34:42

标签: javascript

为什么更改属性的值会更改数组中所有相似属性的值,以及如何在不为this使用'name'关键字的情况下使其正确工作?

let Object = {
	'name' : 'Test Object'
}

let Array = []

Array.push(Object)
Array.push(Object)
Array.push(Object)

Array[0]['name'] = 'Changed'

console.log(Array) // expect only the first name to change, but all 3 change...

3 个答案:

答案 0 :(得分:1)

您不是要更改“名称相似”的对象,而是要更改相同的对象。

对于非基元(基本上不是字符串,数字或布尔值的所有基元),它们通过引用传递。这意味着当您将它们添加到类似数组的内容中或将它们传递给函数时,基本上就是在传递它们的地址。如果您通过3次,则它们都指向同一个地址;仍然只有一本。更改一个,然后全部更改。

const a = { b: 1 };
const arr = [a, a, a];

// All the same object
console.log(arr[0] === arr[1], arr[1] === arr[2], a === arr[0]);

a.b = 5;

// All 3 changed, because it is the same thing
console.log(arr.map(a => a.b));

function someFunc(obj) { obj.b = 10 };

someFunc(a);

// changed from inside function, same object
console.log(a.b); 

如果要创建少数几个都以相同的开始但又可以随后更改的对象,则需要循环创建对象:

const template = { name: 'a' };
const arr = [];

for (let i = 0; i < 3; i++) {
  arr.push({ ...template }); // or: arr.push(Object.create({}, template))
}

arr[1].name = 'b';
arr[2].name = 'c';
console.log(arr);

或更简洁地说:

// Creates a new Array with 3 records and then puts a copy of the template in each.
const template = { name: 'a' };
const arr = new Array(3).fill(1).map(() => ({ ...template }));
// or (without needing template variable):
// const arr = new Array(3).fill(1).map(() => ({ name: 'a' }))

arr[1].name = 'b';
arr[2].name = 'c';

console.log(arr);

答案 1 :(得分:0)

调用Array.push(Object)时,会将对同一对象的引用推入数组3次。推送不会复制Object-仅存在1个Object

如果要在一个数组中包含3个相同的对象,请尝试如下操作:

let vArray = []

for(i = 0; i <= 2; i++) {
    //We're going to loop this 3 times, creating 3 different
    //objects and pushing each of them into the array

    let vObject = {
        'name' : 'Test Object'
    }

    vArray.push(vObject)
}

vArray[0]['name'] = 'Changed'

console.log(vArray) // Only the first one will have been changed.

答案 2 :(得分:-1)

我正在寻找的答案是更改对Array.push({...Object})的回答的语法。这将创建一个要推送的“新”对象,仅包含5个附加字符...

我不知道“对象传播语法”实际上是这样做的。