a.x = a = { }, 深入理解赋值表达式(转)

原帖 http://lifesinger.org/blog/2010/10/a-x-a/
a.x = a = { }, 深入理解赋值表达式

Posted on October 15th, 2010 in 思考 by lifesinger

直奔代码:

var a = {x: 1};
a.x = a = { };
alert(a.x); // --> undefined

来自 JE: 写了 10 年 JavaScript 未必全了解的连续赋值运算. clue 的评论已经从 ECMA 规范分析了具体原因,下面尝试更直观的说明此问题。

对于连续赋值语句,我们经常会这样理解:

var a = b = 1;
// 等价:
var a;
a = b = 1;

上面的理解很容易看出 var a = b = 1; 会造成 b 泄漏到上层作用域,有可能生成全局变量。

根据直觉,我们可能会推断:

a = b = 1;
// 等价:
b = 1;
a = b;

如果上面的推断成立,可以得出:

a.x = a = { };
// 等价:
a = { };
a.x = a;
// 因此:
alert(a.x); // --> [object Object]

和实际输出值 undefined 不符。
也就是说,a.x = a = { }; 并不能简单等价为 a = { }; a.x = a;

JavaScript 里,赋值运算是从右到左的,同等优先级下,右边的会先结合:
a.x = a = { } 等价为 a.x = (a = { })

有意思的地方就在这里,对于赋值表达式,解析的规则是:

The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:
1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

上面的规范其实非常简单,比如 a = 1, 步骤就是:

Step1. 计算 a 的值
Step2. 计算 1 的值
Step3. 得到 Step2 的结果
Step4. 将 Step3 的结果赋值给 Step1 的结果
Step5. 返回 Step3 的值

简直是废话啊,但是特别有意思的也就在于 Step1 是最先执行的。理解这一点,问题变得很清晰:

a = b = 1; // 等价 a = (b = 1)
// Step1: 计算 a 的值
// Step2: 计算 (b = 1) 的值
// ...



b = 1;
a = b;
// Step1: 执行 b = 1; 语句
// Step2: 计算 a 的值
// ...

是否已经恍然大悟了?

因此对于 a = {x: 1}; a.x = a = { }:

a.x = a = { } // 等价 a.x = (a = { })
// Step1: 计算 a.x 的值,此时 a.x 指向 {x: 1} 对象的 x
// Step2: 计算 (a = { }) 的值,这一步让 a 指向了一个新对象 { }
// Step3: 得到 Step2 的结果,也就是 { }
// Step4: 将 Step3 的结果赋值给 Step1 的结果,也就是将 {x: 1} 对象的 x 重新赋值为 { }
// Step5: 返回 Step3 的结果

很显然,执行完毕后,a 指向 { }, 因此 a.x 为 undefined.

不光 JavaScript, Java, C++ 等语言也如此。虽然实际项目中,要坚决杜绝这种晦涩代码,但作为语言研究,思考总能让人看到不少显然背后的不显然,以及不显然背后的显然,也算是一种乐趣吧。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值