今天翻JQuery源码的时候,发现了一个很有意思的东西。
window.jQuery = window.$ = jQuery;
我还是第一次见这种连续赋值的代码。遂去论坛查了挺多资料,发现很多说法缺少一些说服力,或者在一些关键环节就一笔带过了。不过千万不要在JS中使用连等赋值操作的作者逻辑很严谨,下的结论让人信服。我在他的论证过程中,再加上一点书本查到的资料补充一下论证,谈谈自己的见解。班门弄斧,若有不足,希望大家指正。
代码:
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);// undefined
console.log(b); // {n:1, x:{n:2}}
大家看到这段代码,肯定对 A = B = C 赋值顺序有两个猜想:
- B = C; A = C;
- B = C; A = B;
若两个变量同时指向一个对象,那么对这个对象的修改是同步的。
我们可以使用ES5中getter特性来测试在赋值的时候,C被读取了几次,从而可以判断哪个猜想是正确的。
我们可以看到,说明c只被调用了一次,所以可以排除猜想1。
得出结论:连续赋值是从右至左永远只取等号右边的表达式结果赋值到等号左侧。
我们继续分析,那么这样的话,我们拆开写的效果是否一样呢?
由此可以看出,并不能拆开写。
那么 a.x = a = {n: 2}; 这段代码是如何执行的呢,请看《js权威指南》里的一段文字:
这话的意思是: js会先从左至右计算表达式的值,最后再从右至左进行赋值操作。
所以,a.x = a = {n: 2}; 首先会计算a.x,此时a仍然和b指向同一个对象{n: 1, x: undefined},接着计算a,然后开始赋值操作, a = {n: 2}; 然后 a.x = a;相当于 b.x = a;所以可以看出旧的a.x和新的a都会指向{n: 2},证明它俩是全等的。
测试:
结果正确。