多重分配混乱 [英] Multiple assignment confusion
问题描述
我知道赋值运算符是正确的关联.
I understand that the assignment operator is right associative.
因此,例如x = y = z = 2
等效于(x = (y = (z = 2)))
在这种情况下,我尝试了以下操作:
That being the case, I tried the following:
foo.x = foo = {a:1}
我希望对象foo
将使用值{a:1}
创建,然后属性x
将在foo
上创建,而该属性只是对foo
对象的引用.
I expected that the object foo
would be created with value {a:1}
and then the property x
will be created on foo
which will just be a reference to the foo
object.
(如果我将多重赋值语句分成两个独立的语句foo = {a:1};foo.x = foo;
,实际上会发生这种情况)
(This is actually what happens if I was to separate the multiple assignment statement into two separate statements foo = {a:1};foo.x = foo;
)
结果实际上是:
ReferenceError:未定义foo(...)
ReferenceError: foo is not defined(…)
因此,我尝试了以下操作:
So then I tried the following:
var foo = {};
foo.x = foo = {a:1};
现在我不再遇到异常,但是foo.x
未定义!
Now I don't get the exception anymore but foo.x
is undefined!
为什么作业无法按预期工作?
免责声明:重复"问题似乎与我要问的完全不同,因为存在一个问题,即分配中创建的变量是全局变量,与创建的变量相对应使用
var
关键字.这不是这里的问题.
Why is the assignment not working as I expected?
Disclaimer: The 'duplicate' question seems to be very different to the one that I'm asking, as the issue there is that the variables that were created in the assignment were global, as apposed to variables created with the
var
keyword. That's not the issue here.
推荐答案
关联性和评估顺序之间存在重要区别.
There's an important difference between associativity and order of evaluation.
在JavaScript中,即使赋值运算符 groups 从右到左,在执行实际赋值之前,操作数也是从左到右评估的( do 从右到左).考虑以下示例:
In JavaScript, even though the assignment operator groups right to left, the operands are evaluated left to right before the actual assignments are performed (which do occur right to left). Consider this example:
var a = {};
var b = {};
var c = a;
c.x = (function() { c = b; return 1; })();
变量c
最初引用a
,但是赋值的右侧将c
设置为b
. a.x
或b.x
被分配了哪个属性?答案为a.x
,因为当c
仍引用a
时,首先评估左侧.
The variable c
initially references a
, but the right-hand side of the assignment sets c
to b
. Which property gets assigned, a.x
or b.x
? The answer is a.x
because the left-hand side is evaluated first, when c
still references a
.
通常,表达式x = y
的计算方式如下:
In general, the expression x = y
is evaluated as follows:
- 评估
x
并记住结果. - 评估
y
并记住结果. - 将步骤2的结果分配给步骤1的结果(并返回前者作为表达式
x = y
的结果).
- Evaluate
x
and remember the result. - Evaluate
y
and remember the result. - Assign the result from step 2 to the result of step 1 (and return the former as the result of the expression
x = y
).
如x = (y = z)
所述,多次分配会发生什么?递归!
What happens with multiple assignments, as in x = (y = z)
? Recurse!
- 评估
x
并记住结果. - 评估
y = z
并记住结果.去做这个:
- Evaluate
x
and remember the result. - Evaluate
y = z
and remember the result. To do this:
- 评估
y
并记住结果. - 评估
z
并记住结果. - 将步骤2.2中的结果分配给步骤2.1中的结果(并返回前者作为表达式
y = z
的结果).
- Evaluate
y
and remember the result. - Evaluate
z
and remember the result. - Assign the result from step 2.2 to the result of step 2.1 (and return the former as the result of the expression
y = z
).
x = (y = z)
的结果).
x = (y = z)
).现在让我们看一下您的示例,对其进行稍加修改:
Now let's look at your example, slightly edited:
var foo = {};
var bar = foo; // save a reference to foo
foo.x = (foo = {a:1}); // add parentheses for clarity
foo.x
是在将foo
分配给{a:1}
之前进行评估的,因此,会将x
属性添加到原始的{}
对象中(可以通过检查bar
进行验证).
foo.x
is evaluated before foo
gets assigned to {a:1}
, so the x
property gets added to the original {}
object (which you can verify by examining bar
).
这篇关于多重分配混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!