zoukankan      html  css  js  c++  java
  • a.x = a = { }, 深入理解赋值表达式

    转载,对原作者深表感谢,学习了!原文地址:http://blogread.cn/it/article.php?id=2623

    直奔代码:

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

  • 相关阅读:
    ES6-10笔记(class类)
    ES6-10笔记(let&const -- Array)
    小程序的表单提交
    小程序表单回显
    小程序template模板的使用和模板多数据传递
    微信小程序的初始配置
    babel 版本原因运行报错,解决办法
    webpack 和 webpack-cli 安装和使用中出现的问题
    jQuery中操作属性的方法attr与prop的区别
    javaScript 添加和移除class类名的几种方法
  • 原文地址:https://www.cnblogs.com/newdefence/p/1867353.html
Copyright © 2011-2022 走看看