【问题标题】:why the program's result is undefined?为什么程序的结果是未定义的?
【发布时间】:2014-02-24 05:00:15
【问题描述】:
 var foo = {};
 foo.c = foo = {};
 console.log(foo.c);

为什么结果是未定义的? 我认为它应该是'[object Object]'

【问题讨论】:

  • 对象通过引用传递。因此foo.c == foo == {}。空对象没有属性c
  • @elclanrs 你的意思是= 而不是==
  • 我的意思是它们是同一个对象,它是一个循环引用。
  • 必须是var foo = {}; foo.c = foo; console.log(foo.c); // 这样可以吗?由于您正在清空 foo
  • 是的,或者var foo = {}; foo.c = foo = {c: foo};

标签: javascript


【解决方案1】:

assignments这里发生了奇怪的事情:

foo.c = (foo = {})

referencefoo.c 首先被解析并指向 old foo 对象,然后计算内部表达式,其中 foo 被重新分配给 {}空对象字面量。所以你的代码相当于

var foo1 = {};
var foo2 = {};
foo1.c = foo2;
console.log(foo2.c) // obviously undefined now

你也可以试试

var foo = {}, old = foo;
foo.c = foo = {};
console.log(old, foo, old.c===foo); // {c:{}}, {}, true

【讨论】:

  • 但是foo.c = foo = {};中的评估顺序不是从右到左吗?即foo首先变为{},然后将该结果分配给foo.c
  • @techfoobar:因为它是从外到内,从左到右。只有运算符优先级是从右到左的。
  • @techfoobar - 根据the spec (section 11.13.1),分配的左侧在评估右侧之前解决。因此,foo.c 在评估右侧(涉及另一个分配)之前被解析为 Bergi 所描述的。
  • 也许我很奇怪,但是深入研究规范并弄清楚这些事情很有趣 :) 干得好!
【解决方案2】:

JavaScript 引擎拆分此类分配:

a = b = c = 1;

如下:

a = 1;
b = 1;
c = 1;

为:

c = 1;
b = c;
a = b;

有一个轻微但重要的区别——主要是涉及到 getter,请查看Multiple variable assignments in one row 了解更多详细信息——这主要是为什么你的代码不像预期的那样运行,因为最初的预期是基于错误的假设。

【讨论】:

  • 其实这是不正确的。该语句被评估为a = (b = (c = 1));。所以分配c = 1首先发生,它的结果(1)被分配给b等。我正在考虑一个很好的方法来证明这一点。
  • 这不是真的@FelixKling。请检查我上面链接的答案,您会发现一段代码演示了 JavaScript 引擎在特定情况下如何工作。
  • 该链接实际上证实了我的说法。你检查变量的顺序了吗?不明白您为什么现在要声明其他内容 :) 要明确:我不是在谈论分配的值,而是在谈论分配的 order。仅此一项并不能解释 OP 获得的输出。
  • 我没有要求其他东西。 :) 可能有误会,我只是说a = b = 1 不等于b = 1, a = b 而是等于a = 1, b = 1。这是 JavaScript 的一个众所周知的行为——我正在研究 spidermonkey。
  • 是的,我明白了。但是在这个答案中,您声称a 首先获得一个值,然后是b,然后是c,而反过来,就像您在其他答案中所写的那样。所以,a = b = 1b = 1, a = 1,而不是 a = 1, b = 1。顺序在这里非常重要。因为这意味着foo.c = foo = {};等价于foo = {}; foo.c = {},这并不能解释为什么console.log(foo.c)显示undefined
猜你喜欢
  • 1970-01-01
  • 2018-05-01
  • 2015-04-19
  • 2018-10-27
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
相关资源
最近更新 更多