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

时间:2016-06-24 08:15:27

标签: javascript

这与Javascript a=b=c statements

有关

我明白了

foo = foo.x = {n: b}; // console.log(foo) => {n: b}

但是

foo.x = foo = {n: b}; // console.log(foo) => {n: b}

它应该等于:

foo = {n: b};
foo.x = foo; // console.log(foo) => {n: b, x:object}

我在这里错过了什么吗?

4 个答案:

答案 0 :(得分:18)

使用:

foo.x = foo = {n: b};

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

它表现得更像:

var oldFoo = foo;
foo = {n: b};
oldFoo.x = foo;

This is mentioned in the standard。 {值{1}}的左侧在放置值(1.f)之前进行评估(1.a):

  

AssignmentExpression LeftHandSideExpression = AssignmentExpression

     

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

答案 1 :(得分:7)

这是因为你写的时候

var foo = {};
foo.x = foo = {n: b} //a=b=c

在执行该行时,foo指向{},但此语句分解为

foo.x = (foo = {n: b}) /a=(b=c)

foo的引用已从{}更改为{n:b}foo(a)中的foo.x仍然指向foo的旧引用,因为在分配开始之前评估左手表达

根据spec

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

         

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

  2.   

这意味着在作业foo.x仍然引用旧foo之前。

所以,如果你做一点点调整你的例子

var foo = {z:2};
foo.x = foo.n = {n: 1};

在此示例中,您未更改对foo的引用,仅分配了新属性,因此现在输出

  

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

现在,它保留了对旧foo的引用,因为未分配新引用,因此保留所有属性znx

答案 2 :(得分:6)

等于

let tmp = foo;
foo = {n: b};
tmp.x = foo;

您可以看到,旧的foo(在此示例中存储在z中)已被修改:

> z=foo={};
{}
> foo.x = foo = {n: b};
{ n: 10 }
> foo
{ n: 10 }
> z
{ x: { n: 10 } }

答案 3 :(得分:1)

我明白了。

var foo = {}; // now foo is a reference point to object {}
foo.x = foo = {n:1}; // first foo is refer to a new object {n:1}, then old foo referred object {} set a prop x

// try this to get what you want
var foo = foo1 = {};
foo.x = foo = {n:1};
console.log(foo, foo1) // here foo1 is what you want