【发布时间】: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)。
标签: javascript jquery object constructor