連續賦值和內存指針的問題解析(a.x=a={n:2})


  前幾天偶然看到了一個這樣的題:

1 <script>
2     var a={n:1};
3     var b=a;
4     a.x=a={n:2};//關鍵代碼
5 console.log(a.x);//undefined
6 console.log(b.x);//[object Object]
7 </script>

     這個題代碼不多,不過考察的知識點卻非常不錯。我們知道內存空間分為棧內存和堆內存。棧內存用來存放供js代碼來執行的環境,所以為了保證性能減少內存占用,我們一般把占用空間較小的類似於基本數據類型放在棧內存中,像引用數據類型這種占據空間比較大的東西,我們需要將它放在一個貯藏室中—堆內存中,堆內存相較於棧內存對js執行時對性能影響很小,雖然引用類型存放在堆內存里了,但是當我們代碼執行時我們也需要用到這部分,所以我們需要將類似於標簽,名字(類似於元素的ID)放置於棧內存中,和堆內存中的東西一一對應,當執行到他時直接去堆內存中找,這種模式就好比古代的銀票和同等價值的黃金和白銀,一個很有錢的商人不能每次出門都推着一車銀子吧,那可是金屬,那這樣有錢人活的就太累了,所以一個等面值的銀票揣在手中,一切問題就搞定了。 所以“不同變量的同一引用數據類型賦值就是指向的是同一個堆內存空間,不會去創造新的內存空間,不然太浪費空間了,你要知道這可是內存,內存呀!!”

   1. 像此題中一樣 var a={n:1};    var b=a;  這是並沒有給變量b在堆內存中在創建一個對象{n:1},而是他倆共同指向內存空間中的{n:1},不論你創建多少個變量去賦值堆內存中始只存在一個{n:1};我們姑且稱呼這個對象為A,草圖如下:

 

 

 

 

 

 

 

2. 接下來我們可以看到此題中有標注‘關鍵代碼’字樣的,他們考察了我們連續賦值,並且還有屬性操作:

a.x = a = {n:2};

 

js的賦值運算順序永遠都是從右往左的,不過由於“.”是優先級最高的運算符,所以這行代碼先“計算”了a.x。

 

所以我們先進行屬性操作,a.x,因為此時x作為a的一個屬性,沒有最開始沒有從右向左賦值時它的值為undefined,這行代碼可以說已經執行了a.x,這時如下圖

 

 

接下來從右向左開始賦值,將a的指向從對象A指向了對象B{n:2},

接下來繼續執行 a.x=a,很多人會認為這里是“對象B也新增了一個屬性x,並指向對象B自己”,很多人這樣認為是錯誤的,根據優先性( .  運算符最先計算),咱們剛才已經計算過a. x,那時變量a的指向還是對象A,變量a指針並沒有發生變化,所以此時a.x確切地說應該是對象A.x,代碼再次執行時,指針發生了變化,a的指針指向B,此時a.x=a再賦值時不再次執行依次a.x然后再賦值,這樣系統不允許,而是直接賦值,相當於之前的A.x賦值,所以 a.x=a 應理解為對象A的屬性x指向了對象B:

 

那么根據圖表很容易得出結果當console.log(a.x)的時候,a是指向對象B的,但對象B沒有屬性x。沒關系,當查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈,直到找到給定名稱的屬性為止。但當查找到達原型鏈的頂部 - 也就是 Object.prototype - 仍然沒有找到指定的屬性B.prototype.x,自然也就輸出undefined;

而在console.log(b.x)的時候,由於b.x表示對象A的x屬性,該屬性是指向對象B,自然也輸出了[object Object]了,注意這里的[object Object]可不是2個對象的意思,對象的字符串形式,是隱式調用了Object對象的toString()方法,形式是:"[object Object]"。

為了驗證咱們的結果我們可以將上面的題進行變種:

1 <script>
2     var a={n:1};
3     var b=a;
4     a={n:2}
5     a.x=a;
6     console.log(a.x);//[object,Object]
7     console.log(b.x);//undefined

8 </script>

  那么與上題的區別就是我們將變量a指針先改變,然后在進行對象屬性的操作a.x。

嘿嘿,如果我們這樣連等呢?

1 <script>
2     var a={n:1};
3     var b=a;
4     a=a.x={n:2};
5     console.log(a.x);
6     console.log(b.x);
7     console.log(a.n);
8     console.log(b.n);
9 </script>

 

 

此時的結果是和第一題的解題思路是一樣的,只要是既有變量和變量屬性的連等賦值的打印元素屬性的值都為undefined

總結:所以我們做此類題時無外乎考慮這幾個知識點連等賦值的優先級別從右向左,不過遇見屬性一切玩完,

 我驗證了一下凡是類似於這樣變量a=a.x=引用數據類型,都可以引用只要是既有變量和變量屬性的連等賦值的打印元素屬性的值都為undefined。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM