ax = a = {n:b}如何在JavaScript中运行?

Lia*_*ang 15 javascript

这与Javascript a = b = c语句有关.

我明白这一点

foo = foo.x = {n: b}; // console.log(foo) => {n: b}
Run Code Online (Sandbox Code Playgroud)

foo.x = foo = {n: b}; // console.log(foo) => {n: b}
Run Code Online (Sandbox Code Playgroud)

它应该等于:

foo = {n: b};
foo.x = foo; // console.log(foo) => {n: b, x:object}
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么吗?

Jon*_*ski 18

附:

foo.x = foo = {n: b};
Run Code Online (Sandbox Code Playgroud)

foo.x首先部分评估前导,足以确定分配的确切目标,然后再继续实际分配.

它表现得更像:

var oldFoo = foo;
foo = {n: b};
oldFoo.x = foo;
Run Code Online (Sandbox Code Playgroud)

这在标准中提到.的左侧=进行评估(1.A)的值放在那里(1.F)之前:

AssignmentExpression:LeftHandSideExpression = AssignmentExpression

1)如果LeftHandSideExpression既不是ObjectLiteral也不是ArrayLiteral,那么
a)lref成为评估LeftHandSideExpression的结果.
...
f)执行?PutValue(lref,rval).


gur*_*372 10

这是因为你写的时候

var foo = {};
foo.x = foo = {n: b} //a=b=c
Run Code Online (Sandbox Code Playgroud)

当行正在执行时,foo指向{}但是当这个语句被分解为时

foo.x = (foo = {n: b}) /a=(b=c)
Run Code Online (Sandbox Code Playgroud)

foo的引用已经从改变{}{n:b}但是foofoo.x(a)中仍然指向旧的引用,foo因为在赋值开始之前评估了左手表达式.

按照规范

  1. 如果LeftHandSideExpression既不是ObjectLiteral也不是ArrayLiteral,

    一个.然后让lref成为评估LeftHandSideExpression的结果.

这意味着在任务之前foo.x仍然提到旧的foo.

所以,如果你稍微调整一下你的例子

var foo = {z:2};
foo.x = foo.n = {n: 1};
Run Code Online (Sandbox Code Playgroud)

在此示例中,您没有更改引用foo,仅分配了新属性,因此现在输出为

对象{z:2,n:对象,x:对象}

现在,它保留了对old的引用,foo因为没有为新引用分配所有属性z,n并且x正在保留它.


Ale*_*Ten 6

它等于

let tmp = foo;
foo = {n: b};
tmp.x = foo;
Run Code Online (Sandbox Code Playgroud)

你可以看到,旧的foo(存储z在这个例子中)被修改了:

> z=foo={};
{}
> foo.x = foo = {n: b};
{ n: 10 }
> foo
{ n: 10 }
> z
{ x: { n: 10 } }
Run Code Online (Sandbox Code Playgroud)