8

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

 4 years ago
source link: https://blogread.cn/it/article/2623?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

浏览:2613次  出处信息

直奔代码:

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.xundefined.

不光 JavaScript, Java, C++ 等语言也如此。虽然实际项目中,要坚决杜绝这种晦涩代码,但作为语言研究,思考总能让人看到不少显然背后的不显然,以及不显然背后的显然,也算是一种乐趣吧。

觉得文章有用?立即:

和朋友一起 共学习 共进步!

建议继续学习:

  1. 写了10年Javascript未必全了解的连续赋值运算    (阅读:2466)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK