a.x = a = { }, 深入理解赋值表达式
来源:互联网 发布:被五步蛇 知乎 编辑:程序博客网 时间:2024/05/17 16:55
直奔代码:
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++ 等语言也如此。虽然实际项目中,要坚决杜绝这种晦涩代码,但作为语言研究,思考总能让人看到不少显然背后的不显然,以及不显然背后的显然,也算是一种乐趣吧。
转自:http://lifesinger.org/blog/2010/10/a-x-a/
- a.x = a = { }, 深入理解赋值表达式
- 连续赋值与求值顺序var a = {n:1};a.x = a = {n:2}; alert(a.x);
- 连续赋值与求值顺序var a = {n:1};a.x = a = {n:2}; alert(a.x)
- 深入理解++a和a++
- a.x=a={n:1} JS中使用连等赋值操作
- a^=b^(b^=a^b)——连续赋值表达式的陷阱
- JAVA 对象引用,以及对象赋值-深刻理解A a1 = new A()这句话
- 连续赋值与求值顺序var a = {n:1};a.x = a = {n:2}; alert(a.x); // --> undefined
- 深入理解JavaScript赋值表达式(一)
- A+B=X
- a<=1 && !x++
- 深入理解int a[5];
- url链接(<a href=>hefr参数的赋值</a>)
- 中缀表达式X=A+B*(C-(D+F))/E转后缀表达式之后是什么?
- 深刻理解A a1 = new A();
- A(A& other,int x=0)//*/ A(const A& other,int x=0)
- 对于 A a = new A(); 的一些理解
- 如何理解变量赋值(如: int x = 1;)
- 欧美投资者开始大举买进阿里巴巴股票
- phpMyadmin配置
- 有没有想过,也许一辈子你都是个小人物。(转自豆瓣)
- 移动互联网
- 强连通分支
- a.x = a = { }, 深入理解赋值表达式
- 设计模式 Design Parttern ——享元模式FlyWeight
- (转)使用MFC的WinINet库来实现图片文件的上传
- 在函数中arguments的使用
- 如何确定计算机运行的是 32 位还是 64 位版本的 Windows 操作系统
- 程序员职场第一课
- 经典....
- CSDN 第一篇
- HOJ