赋值顺序
以下为网上一个非常经典的面试题:
var a = {n: 1}
var b = a;
a.x = a = {n: 2}
console.log(a.x);
console.log(b.x)
OK我们来解答一下
声明!!!曾经的认知:
第一个知识点:
b = a 是浅拷贝,所以在堆栈中引用的是一个对象地址。
第二个知识点:
var a=1,b=2,c=3;
a = b = c;
输出的a,b,c结果都为3。 因为赋值运算从右向左执行。
而我们这道题 a.x = a = {n: 2}
. 的运算优先级大于赋值运算的优先级。
所以先计算
再计算
所以截止到现在
a的输出值:{ n:2 };
b的输出值:{ n:1 , x={n:2} }
OK, 看明白了我们随便改动来练习一下:
所以截止到现在
a,b的输出都是一个值:{n={n:2}, f={n:2}}
我们来验证一下:
新的认识:
在阅读了javascript引擎的原理解析后有了新的认识。
此题的衍化源自于Jquery的提交者之一 蔡美纯(蔡mc)
虽然按上述文章的思路算的题结果是没问题的,但是概念的理解是有误区的,所以在这里重新阐述一下。
JavaScript的计算是从左至右的
例:
var a = x + y * z
a在此处是个字面量,后面的为表达式,计算后赋值给a
var a = {n:1} a.x = a = {n: 2}
a.x在此处是个表达式,所以参与从左到右的运算(此处纠正:历史的阐述是 . 的运算符优先于 = 赋值运算符)
此处可以用Object.freeze(a)冻结a去验证,可以清晰验证结论。
解析:
a.x = " 表达式 a={n:2} ",表达式将计算结果赋值给a.x
a = {n:2}的结果为{n:2}
注:a 在此过程中被真实的赋值了一次 {n: 2},但是 a.x 中的 a 此时不会更新,它等待的是一个运行结果,这个结果只有引擎知道,对于它的操作只能为取值或置值(GetValue/PutValue),以及作为一个引用向别的地方传递等。实际上a的值已经为{n: 2},但体现不出来,相当于被"空置"了。
b=a是先行的,a.x中的a等待的运行结果为: {n:1, x:{n:2}} 。
如果将 var b=a放在a.x之后,结果就会等于空置的a
所以
a的输出值:{ n:2 };
b的输出值:{ n:1 , x:{n:2} }
扫描二维码关注公众号
每日好文伴你地铁时光。