最近在看到以前前輩留下的文章,對於連續賦值( var a={n:1}; a.x=a={n:2}) )這個知識點,一開始也搞不清楚,但是最終還是說服了自己,談談自己的心得。以下代碼能回答正確的可以忽略本文。
1 var a={n:1}; 2 var b=a; 3 a.x = a = {n: 2}; 4 console.log(a.x); //? 5 console.log(b.x);//?
正確答案是:
a.x= undefined;
b.x= {n: 2};
疑惑:為什么a.x與b.x不相等呢?為什么a.x會等於undefined呢?
如果你答錯了,那么請你往下看。
javascript中的引用賦值
很清楚的一點是:js中對象的賦值其實是引用的賦值,只是將b對象的引用指針指向了a對象的引用。
1 var a={n: 1}; 2 var b= a; 3 console.log(b.n); // 1 4 a.n=2; 5 console.log(b.n); // 2
上面的代碼對於一個程序員來說應該都沒有理解上的問題。
賦值運算符的右結合
也就是說賦值運算符是從右向左運算的,這個倒不難理解,例如 var a = 1 + 2; 先計算了等號右邊1+2,將右邊的結果3賦值給了a;當然你也許會說這是運算符的優先級;其實這里本文想要表達的是賦值運算是將“=”右邊賦值給左邊。下面這個例子應該會更加幫助你理解。
1 var a, b; 2 a=b=1+2;
其中按照賦值運算符的右結合的特質:
a = b = 1 + 2 等價於 a = (b= 1+2 )
其中 b 等於 1+2的返回值 3 ;
a 等於 b=3 的返回值 3;
賦值運算符運算順序:從左到右
雖然上面講到賦值運算符是從右向左運算的,但是其運算順序是從左往右的。也就是說本文一開始提出的問題 a.x = a = {n:2} 是從左向右運算的(賦值是從右向左);也就是說程序的計算順序是:
1 a.x 2 a 3 {n:2}
程序執行到 a.x = a = {n:2} 先執行a.x 並等待賦值符號“=”后面的運算返回值;然后執行a並等待賦值符號“=”后面的運算返回值。
答案是這樣來的
如果看到這有點繞進去了,分析一下本文一開始提出來的例子應該會幫助你更好地了解:
1 var a={n:1}; 2 var b=a; 3 a.x = a = {n: 2};
1. 變量a指向了一個對象{n:1};
2. 變量b指向了a的引用(其實就是{n:1});
3. 計算a.x並等待賦值符號“=”后面的運算返回值(此時,a指向的是{n:1});
4. 計算a並等待賦值符號“=”后面的運算返回值,注意這里將a的引用指向了{n:2};
到這里你是否看出了,第3步a.x的a是{n:1};第4步的a已經被改成了{n:2};
因此當console.log(a.x)的時候就肯定是undifined了;而console.log(b.x)為{n:2};
如果到這里還不明白,不妨再增加兩個變量 obj1, obj2; 令obj1={n:1}; obj2={n:2}
1 var obj1={n:1}; 2 var obj2={n:2}; 3 var a=obj1; 4 var b=a; 5 a.x=a=obj2; 6 console.log(a.x); //undefined 7 console.log(b.x); //{n:2} 8 console.log(obj1); //{n:1, x:{n:2}} 9 console.log(obj2); //{n:2}
其實 a.x=a=obj2 等價於
a=obj2;
obj1.x=obj2;
作者:AlvinWei 文章出處:韋躐晟的博客 http://www.cnblogs.com/alvinwei1024/p/4856623.html
本文版權歸作者和博客園共有,歡迎轉載
轉載請說明原文章出處
最后
寫代碼時要搞清楚變量間的引用關系,一般情況下不要寫這種容易誤導自己和他人的代碼。我想這種情況一般只會出現在面試題里,用來考核對基礎知識的掌握度。