面试题——连等号的优先级
题目:
var a={n:1};
var b=a;
a.x =a ={n:2};
console.log(a.x);
console.log(b.x);
答案:
alert(a.x);// --> undefined
alert(b.x);// --> {n:2}
讲解:
估计大部分人对a.x=undefined存在疑问。
这里将原则总结为一句话:
代码的执行顺序,先从左到右扫描变量,再从右到左进行赋值
扫描阶段:
在a.x = a = {n:2}中,首先扫描到a.x,a.x不存在,所以默认指向null,即a.x=>null。然后扫描到a,a已经存在,所以仍然指向原来的对象,而此时a的指向仍然为{n:1},即a=>{n:1}。
赋值阶段:
在a.x = a = {n:2}中,首先赋值最右边。 a = {n:2},让a指向了{n:2},即a=>{n:2}。继续赋值a.x,(重点)此时的a.x中,a的指向没有改变,可以理解为a.x中的a保留了原来的镜像。也就是原对象变为{n:1,x:{n:2}},而此时只有b指向原对象。
因此最终输出的时候
console.log(a.x) 此时a.x中的a已经彻底指向了新对象。输出的是新对象中的x属性值。而老对象中的x属性也已经不再叫做a.x了。至于叫做什么不得而知。
console.log(b.x) 输出的是老对象中x属性值。
老对象为 {n:1,x:{n:2}}
新对象为{n:2}
因此a.x自然取不到值,为undefined。
如果我们再次赋值 a.x = 3;
则输出结果为 console.log(a.x) // {n:2,x:3}。表明原来的a.x已经被删除,在新的a对象中新建了属性x。
其实核心的原理就是 “.”优先级高于"=",所以先保留了指针,后进行了赋值,然后进行了gc,发现a的指向已经改变,删除了原来的指针a.x。
最后一图胜千言
QQ截图20171103162519.png