什么时候需要使用 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.log
s,最终得到了相同的值。没什么区别。无论如何,我只是看不到那个小提琴中的意外行为。也许把你得到的输出放在你的问题中,并指向你期望其他东西的行。
为什么leftChoice.id
设置为该值后不能立即成为 444?当然,rightChoice.id
现在也会给出 444,因为它们仍然指向同一个对象。
它会在你分配给它时改变它的值。很可能您在记录它之前已经覆盖了它(可能通过指向同一个对象的rightChoice
)。
【参考方案1】:
Object.Assign 为左鞋创建一个新的 COPY,包括所有可枚举的 OWN 属性。当您使用 leftshoe = righthoe 时,您正在对左鞋进行参考。引用指向同一个对象,而不是新副本。因此,正如您所指出的,更改引用的属性实际上是更改了原始属性。
【讨论】:
谢谢!所以我不得不问,为什么我链接到的 JSFiddle 不是这种情况?我使用参考分配,但仍然能够进行更改。查看我的 Fiddle 的第 35 行,然后浏览我在查看输出时制作的按钮。 小提琴对我来说似乎坏了。 rightId 在应该保持 999 时被设置为 444 非常感谢,现在使用它与 redux 反应更有意义以上是关于什么时候需要使用 Object.assign() 方法来复制一个对象的实例?的主要内容,如果未能解决你的问题,请参考以下文章