JavaScript變量存儲淺析(一)


Hello!

  上一篇關於JS中函數傳參(http://www.cnblogs.com/souvenir/p/4969092.html)的介紹中提到了JS的另外一個基本概念:JS變量存儲,

  今天我們就用一個簡單的JS DEMO來開始介紹這個概念。

1 var a = 100;
2  
3 function func(){
4     console.log(a);
5     var a=200;
6     console.log(a);
7 }
8  
9 func();

  相信大家心里面已經有了各自的答案。

  ....

  來看下實際的運行結果:

  

  納尼!怎么會醬紫?我們明明定義了一個全局變量a,按照JS作用域鏈的理論,func應該可以訪問到全部變量a的啊?

  是的,按照作用域鏈的思想,func函數在運行時,在其局部變量內找不到a變量的話,理應向上在全部作用局中繼續查找。

  問題就出在函數內部的 var a =200; 這句局部變量定義。

 

  我們都知道JS變量類型是松散型,松散型的意思並不是說JS變量就沒有變量類型,而是其變量類型是在運行時才進行確定。

  來看一個DEMO:

1 var str;
2 
3 str=2015;

  第一行我們定義了一個變量str,但是並未賦值,這時候JS並不知道str變量的類型,等到腳本運行到第3行,我們給str變量賦了一個值:2015.

  這時候JS才知道,哦,原來str的值是2015,這不就是Number類型嗎,這才確定了str的類型。

  

  這讓我想起了JS的另一個概念,叫作函數聲明提升!

  把最開始的DEMO改造下:

 1 var a = 100;
 2 
 3 func();
 4  
 5 function func(){
 6     console.log(a);
 7     var a=200;
 8     console.log(a);
 9 }
10  

  將函數的聲明放在了最后,但是代碼仍然可以正常運行,並不會出現func未定義的錯誤。

  函數聲明提升就說明JS在運行之前還會經歷另外一個過程:預加載。(有些地方也叫作預編譯)

  在預加載階段,JS主要對全局作用域、函數的運行環境以及作用域鏈等進行准備,

  這里的函數運行環境就是指:讀取變量定義並確定其屬於哪個作用域,但不會為其賦值!

  

  到這里我們終於要開始解釋文章一開始提出的問題了(可憋死寶寶了(づ。◕‿‿◕。)づ):

  我們就來分解一下預加載階段,JS都做了什么事情:

1 var a = 100;    //定義一個全部變量
2   
3 func();
4 
5 function func(){
6     console.log(a);
7     var a=200;        //定義一個func局部變量
8     console.log(a);
9 }

  在預加載階段,第一行的時候定義了一個全部變量a,然后到了第7行,又給func定義了一個局部變量a,

  注意這個時候變量並未賦值,值均為undefined

  到了運行階段:

  第一行給全部變量a賦了值:100,等到執行func函數的時候,

  在第6行,需要使用a變量,JS當然是先查找func的局部變量了,沒錯,預加載階段已經為func定義了一個局部變量a,

  所以JS當然不會繼續往全局進行查找了,但是使用的時候才發現居然沒有值,也就是undefined!

  等到第7行JS才給局部變量a賦值。

 

  小結:

    JS分為預加載和執行期兩個階段,前者只會確定變量的作用域,在執行期才會對齊進行賦值,同時也就確定了變量的具體類型。

  

  

  

   下一篇(http://www.cnblogs.com/souvenir/p/4969565.html)我們將繼續介紹JS中變量的存儲原理,只不過這次我們重點要看的是對象!

  

  

  

  


免責聲明!

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



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