Object.assign 是如何工作的?

How does Object.assign work anyway?

我正在尝试更改数组中的字段。我使用 find 函数获取对象,然后使用 Object.assign 覆盖数组中的值。

但是,在一种情况下有效:

Object.assign(item2, {id:3, name: "Do"});

而在另一种情况下,它不会:

item = Object.assign({}, {id:3, name: "Do"});

这两种情况有何不同?

let arr = [{id:1, name:"John"}, {id:2, name: "Doe"}];
let item = arr.find((x)=> x.id === 2);

//the array is not changed!
item = Object.assign({}, {id:3, name: "Do"});
console.log(arr);

let item2 = arr.find((x)=> x.id === 2);
//the array is changed!
Object.assign(item2,  {id:3, name: "Do"});
console.log(arr);

来源:http://jsbin.com/mametudemo/1/edit?html,js,console

在第一种情况下,您创建一个新对象并将其分配给 itemarr[1] 不会改变,因为你没有使用它的引用,比如

arr[1] = Object.assign({}, { id: 3, name: "Do" });

使用第二种方法,您获取对象并更改给定对象的属性。

let arr = [{ id: 1, name: "John" }, { id: 2, name: "Doe" }];
let item = arr.find((x) => x.id === 2);

item = Object.assign({}, { id: 3, name: "Do" });
console.log(arr);                                // the array is not changed!

let item2 = arr.find((x) => x.id === 2);
Object.assign(item2, { id: 3, name: "Do" });
console.log(arr);                                // the array is changed!

您的代码中有一个 typo/error 导致它无法运行。

第一次尝试更改您使用的对象时 item = Object.assign({}, {id:3, name: "Do"});。注意 {} 作为 Object.assign 的第一个参数...应该是 item

let arr = [{id:1, name:"John"}, {id:2, name: "Doe"}];

let item = arr.find((x)=> x.id === 2);
//the array is not changed!
Object.assign(item, {id:3, name: "Do"});
console.log(arr);

let item2 = arr.find((x)=> x.id === 3);
//the array is changed!
Object.assign(item2,  {id:3, name: "Doa"});
console.log(arr);

事情是这样的。你找到 item:

let item = arr.find((x)=> x.id === 2);

此时item是对相应数组元素的引用。稍后做作业时:

item = Object.assign({}, {id:3, name: "Do"});

你将 item 的值(之前它是一个引用)覆盖为一个新对象,它不再是对原始数组的引用。因此数组不受影响。

Object.assign 的第一个参数是 target

这用于附加属性,然后对同一对象的引用被 return编辑。

所以在第一种情况下,属性被添加到现有对象 item2。但是如果你将它分配给一个变量说 temp 并执行 temp.id = 10,这也会在 item2

中改变

为了避免这种情况,使用了item = Object.assign({}, {id:3, name: "Do"});。这将复制空白对象中的所有属性及其引用 return。所以基本上你已经复制了对象而不仅仅是引用。

你有

let item = arr.find((x)=> x.id === 2);

let item2 = arr.find((x)=> x.id === 2);

在这两种情况下,变量都是指向同一对象的 "reference",该对象包含在数组 arr 中。这意味着如果您更改其中任何一个,这些更改会反映到其他对象(甚至在数组中),因为它们实际上指的是完全相同的对象。

现在,您以两种不同的方式修改这两个变量。在这种情况下

Object.assign(item2, {id:3, name: "Do"});

您正在将新值合并到 item2 中,因为它是一个引用,所以更改会反映到数组中。

第二种情况:

item = Object.assign({}, {id:3, name: "Do"});

您正在将新值合并到一个全新的对象中(assign {} 的第一个参数)然后您覆盖 变量 item用它。现在 item 不再是对数组内部对象的引用。它是一个新对象,因此数组中的对象没有被触及。