什么时候需要使用 Object.assign() 方法来复制一个对象的实例?

Posted

技术标签:

【中文标题】什么时候需要使用 Object.assign() 方法来复制一个对象的实例?【英文标题】:When is it necessary to use the Object.assign() method to copy an instance of an object? 【发布时间】:2016-08-12 07:34:30 【问题描述】:

以下是我为自己解决这个问题而编造的一个示例场景。如果您想直接跳到技术细节,请参阅下面的“技术细节”。

我有一个学习 javascript 的个人项目。基本上,用户可以通过选择可用选项来设计鞋子。

诀窍是左右鞋必须具有相同的尺寸以及其他属性,但颜色、鞋带纹理等内容可以是每只鞋的独立属性。 (我认为这是我练习对象操作和继承的一种不错的方式。

用户从设计合适的鞋子开始;当单击“交换”按钮查看左鞋时,用户当前看到的是右鞋的副本(但倒置)。 只有在第一次换鞋时,左鞋才会生成并精确复制右鞋。从那时起,每个鞋子方向的唯一选项都将保留。 然后,如果用户对 那个左鞋模型进行特定更改,然后切换到右鞋,则假定用户在他们点击“交换”按钮之前看到他们最初设计的完全相同的鞋子。

所以如果他们的右鞋有红色鞋带,他们切换到左鞋视图并让左鞋有蓝色鞋带,然后当切换回右鞋时,用户应该看到红色鞋带!


技术细节

当我为我的主要项目编写代码时,我遇到了保留唯一选项的麻烦。例如,如果我将左鞋的鞋带设为绿色,那么右鞋的鞋带将始终为绿色。解决问题很容易,因为唯一一次右鞋失去了它独特的选择,例如红色鞋带,是我为左鞋设置鞋带颜色的时候。

console.log("THE RIGHT LACE BEFORE: " + rightShoe.laceId);
leftShoe.laceId = 'green';
console.log("THE RIGHT LACE AFTER: " + rightShoe.laceId);

记录到控制台的内容是:

之前的正确花边:红色

之后的正确花边:绿色

即使我没有更改 rightShoe,但只要我更改 leftShoe 属性,它就会被更改。

所以我回到我第一次定义 leftShoe 对象的地方,这是用户在脚本生命周期中第一次单击“交换”时(我的业余想法是 为什么要传播和填充leftShoe 对象,如果用户可能永远不会自定义左鞋? 也许它对数据过于吝啬,我不知道)。从那时起,我再也没有将leftShoe 重新定义为rightShoe 的副本,反之亦然。我认为我可能正在做对象引用,并且就像其他语言一样,我正在更改 reference 而不是值。

在遇到麻烦之前,我想制作一个 JSFiddle 来重现问题。由于我的项目很长(大约 1500 行,包括一些用于图形的 THREE.js),我尽我所能模拟这个过程。所以here it is。

除了 JSFiddle 完全按照我的预期工作! 左侧模型保留了它的唯一属性和该属性的数据集。所以,我做了更多的挖掘并阅读了 Object.assign() 方法。所以在我原来的项目代码中(不是小提琴),我改变了这个:

leftShoe = rightShoe;

到这里:

leftShoe = Object.assign(, rightShoe);

虽然我很高兴终于可以让它工作,但我同样感到好笑和困惑,因为我不明白为什么我的 JSFiddle 不需要 assign() 方法,但我的相同项目代码却需要。谢谢。

【问题讨论】:

在第一种情况下,两个变量都引用同一个对象。在第二种情况下,您将创建一个新对象 () 并使用 Object.assign 复制所有属性。改变一个对象不会反映在另一个对象中。 @Bergi 谢谢,我认为这对我来说很有意义。与其他语言相当标准。但是现在让我失望的是我的 JSFiddle。如果您在我链接的 Fiddle 的第 35 行查看我的引用分配,您会发现 left 选项的值正在更改,而与它是一个被引用对象的事实无关。 你没有,你写了两个console.logs,最终得到了相同的值。没什么区别。无论如何,我只是看不到那个小提琴中的意外行为。也许把你得到的输出放在你的问题中,并指向你期望其他东西的行。 为什么leftChoice.id 设置为该值后不能立即成为 444?当然,rightChoice.id 现在也会给出 444,因为它们仍然指向同一个对象。 在你分配给它时改变它的值。很可能您在记录它之前已经覆盖了它(可能通过指向同一个对象的rightChoice)。 【参考方案1】:

Object.Assign 为左鞋创建一个新的 COPY,包括所有可枚举的 OWN 属性。当您使用 leftshoe = righthoe 时,您正在对左鞋进行参考。引用指向同一个对象,而不是新副本。因此,正如您所指出的,更改引用的属性实际上是更改了原始属性。

【讨论】:

谢谢!所以我不得不问,为什么我链接到的 JSFiddle 不是这种情况?我使用参考分配,但仍然能够进行更改。查看我的 Fiddle 的第 35 行,然后浏览我在查看输出时制作的按钮。 小提琴对我来说似乎坏了。 rightId 在应该保持 999 时被设置为 444 非常感谢,现在使用它与 redux 反应更有意义

以上是关于什么时候需要使用 Object.assign() 方法来复制一个对象的实例?的主要内容,如果未能解决你的问题,请参考以下文章

ES6高级函数Array.reduce()和Object.assign()

Object.assign的用法

前端系列——Object.assign的正确使用与错误示范

对象传播与 Object.assign

Object.assign使用的方法

Object.assign方法的使用