這幾天看了一下JS高級程序設計裏的介紹做用域的章節,也參考了網上的資料,如今結合着本身的理解,給你們分享一下我本身對JS做用域的理解。前端
這裏有三個重要的概念:執行環境、做用域、變量對象函數
(JS高級程序設計解釋)
執行環境 :定義變量或函數可訪問的其餘數據,來決定它們的行爲。
變量對象 :保存執行環境中定義的變量和函數。
做用域鏈 :保證對環境中定義的變量和函數的有序訪問。設計
通俗來講,執行環境和做用域就是變量或函數有效執行所在的一個環境。
總結一下這三者的關係:每一個執行環境執行時都會產生一個做用域,做用域前端都有一個變量對象來保存環境中的變量和函數。code
知道這3個重要概念後,要想搞清做用域,就要先清楚JS程序的預解析過程:
JS程序開始執行時會先解析語法(檢查錯誤等等)、解析內存,而後把function、var解析到變量對象裏。
這裏注意解析var變量時只是會把變量名稱解析,而等到程序運行到變量賦值時纔會向變量賦值。對象
var a="A"; function test(){ console.log(a);//undefined var a="B"; } test();
這段代碼的第一個console.log之因此會是undefined,緣由是函數內部的a變量在預解析時已經被解析到變量對象裏,但沒被賦值。因此函數執行時找到函數裏未被賦值的a變量,輸出undefined。內存
搞清楚預解析後,在判斷做用域範圍:
由於做用域的查找順序是由局部做用域一步步地往上找,直到找到聲明的變量和函數或已經到了全局做用域。因此局部的做用域能夠訪問到外部做用域的變量,而外部做用域訪問不到內部做用域的變量。作用域
var a="A"; function test(){ console.log(a);//「A」 a="B"; } test(); console.log(a);//"B"
function test(){ b();//函數b會被預解析,所以能夠調用,執行了輸出1; var a=1; function b(){ console.log(1); console.log(a);//undefined var a=2; } } test();
以上例子參考網上資料。io
要想搞清做用域,首先要搞清預解析,而後判斷做用域範圍,先判斷本層環境有無聲明及賦值,若是有聲明,則判斷調用前是否賦值。若是找不到聲明,則一層層往外部的做用域找,直到全局環境也找不到時,一般就會報錯。console
若是有解釋的不對或不清晰的,歡迎留言討論。function