【问题标题】:Why is the value of foo.x undefined in foo.x = foo = {n: 2}? [duplicate]为什么 foo.x = foo = {n: 2} 中 foo.x 的值未定义? [复制]
【发布时间】:2016-01-21 20:01:33
【问题描述】:

这段代码:

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

你能解释一下这是什么意思吗:

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

我看到{n:2} 已分配给foo。为什么undefined 分配给foo.xfoo = {n: 2}; 是否返回 undefined

【问题讨论】:

  • 为什么投反对票?这是一个有趣的问题。
  • @Juhana 你介意修改你的编辑吗?
  • @djechlin 有什么问题?
  • @Juhana 你恢复了格式和语言改进。
  • @djechlin 我看不出“此代码”是如何改进的,但 YMMV。

标签: javascript


【解决方案1】:

According to the spec,首先计算赋值表达式的左侧,即使运算符具有从右到左的优先级。因此与foo.x = (foo = {n: 2}) 相同的表达式foo.x = foo = {n: 2} 的求值方式如下:

  1. 计算左侧表达式 foo.x 以获取引用,这是右侧表达式的值将被分配到的位置。

  2. 计算右边的表达式,以获得将要分配的值。右侧是另一个赋值表达式,因此它的求值方式相同:

    1. 评估 foo 以确定分配到的位置。
    2. 计算创建对象的表达式{n:2},以确定要分配的值。
    3. {n:2} 分配给foo,并返回{n:2}

  3. 将右侧表达式计算为 ({n:2}) 的值分配给在步骤 1 中 foo.x 解析为的引用(之前 foo 被分配了一个新的价值)。也和bar.x一样,因为前面一行赋值bar = foo

完成此操作后,bar 仍是对其的引用的原始对象将具有引用所创建的第二个对象的 x 属性。 foo 也是对第二个对象的引用,所以 foo === bar.x

【讨论】:

  • 看来我们赢了。
  • foo.x = (foo = {n: 2}) 有什么意义不应该是相反的,我刚刚也在 chrome 中测试过,结果是一样的
  • @johnny5 如果foo 还不是一个对象,那就没有意义了,但从第一条语句开始,它就是一个对象。
  • 整个重复问题链接中的最佳答案。
  • @Paulpro 是 foo.x = foo = {n: 2};分解为 foo.x = {n: 2}; foo = {n: 2}; ?
【解决方案2】:

因为左侧的属性访问 foo.x 在右侧之前评估。

让我们通过为正在评估的临时表达式赋予新名称来更清楚地说明您的代码实际做了什么:

var foo0 = {n: 1};
var foo1 = {n: 2};
foo0.x = foo1;
foo0 = foo1;
console.log(foo0.x);

因此foo0.xfoo1.xundefined

在您的原始代码中,您可以看到bar.x{n: 2},确认了这个解释。

【讨论】:

  • 我现在看到这是正确的,但它让人们感到困惑并不奇怪。
【解决方案3】:

根据 JavaScript 规范,总是先计算左侧:

12.14.4 运行时语义:评估

AssignmentExpression[In, Yield] : LeftHandSideExpression[?Yield] = AssignmentExpression em>[?In, ?Yield]

如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral,则
1. 令 lref 为评估 LeftHandSideExpression 的结果。

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-assignment-operators-runtime-semantics-evaluation

如果再添加一个foo对象的引用就可以清楚地看到:

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

ref.x 存在是因为foo.x 指的是foo 的未修改值。

【讨论】:

    【解决方案4】:

    因为您将 foo 重新分配给具有单个属性 { n: 2 } 的对象。

    在 JavaScript 中,表达式是从右到左计算的。因此,当您尝试访问foo.x 时,您是在尝试从新分配的foo 值{ n: 2 } 中获取x 的值,即undefined

    【讨论】:

    • 那么 "foo.x = "... 是做什么的?
    • @djechlin 它被分配给 foo,但随后 foo 被覆盖为没有 x 值的对象
    猜你喜欢
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多