【问题标题】:How does a.x = a = {n: b} work in JavaScript?a.x = a = {n: b} 在 JavaScript 中是如何工作的?
【发布时间】:2016-10-26 19:03:55
【问题描述】:

这与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}

我错过了什么吗?

【问题讨论】:

  • console.log(foo.x) 应该打印出同样的内容。
  • 我收到一个错误“无法设置未定义的属性 'x'”
  • 我看不出第一行是如何工作的,除非foo 已经引用了某个对象。 (实际上同样适用于第二个,尽管直觉上第二个“感觉”应该按原样工作。)
  • 你说它应该相等,没有任何理由。没有理由,因为陈述是错误的。 你能解释一下为什么你相信这个错误的东西?它有助于我理解为什么人们相信关于编程语言的错误信息。

标签: javascript


【解决方案1】:

等于

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 } }

【讨论】:

  • 其他答案描述了这就是正在发生的事情,但是 tmpfoo 最初具有与其值相同的对象的示例使这一点更加清晰。
【解决方案2】:

我明白了。

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

【讨论】:

    【解决方案3】:

    与:

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

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

    它的行为更像是:

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

    This is mentioned in the standard= 的左侧在值被放置到那里 (1.f) 之前被评估 (1.a):

    AssignmentExpression : LeftHandSideExpression = AssignmentExpression

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

    【讨论】:

      【解决方案4】:

      这是因为你写的时候

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

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

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

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

      根据spec

      1. 如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 数组字面量,

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

      这意味着在分配之前foo.x 仍然引用旧的foo

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

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

      在这个例子中,你没有改变对foo的引用,只是分配了新的属性,所以现在的输出是

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

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

      【讨论】:

        猜你喜欢
        • 2015-02-09
        • 1970-01-01
        • 2015-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-21
        • 2014-01-29
        • 2016-04-27
        相关资源
        最近更新 更多