3.10.3作用域鏈

JavaScript是基於詞法作用域的語言:通過閱讀包含變量定義在內的數行源碼就能知道變量的作用域。全局變量再程序中始終都是有定義的。局部變量在聲明它的函數體內以及所嵌套的函數內始終是有定義的。

如果將一個局部變量看作是自定義實現的對象的屬性的話,那麼可以換個角度來解讀變量作用域。每一段JavaScript代碼(全局代碼或函數)都有一個與之關聯的作用域鏈(scope chain)。這個作用域鏈是一個對象列表或者鏈表,這組對象定義了這段代碼“作用域中”的變量。當JavaScript需要查找變量X的值的時候(這個過程稱作“變量解析”),它會從鏈中的第一個對象開始查找。如果這個對象有一個名爲X的屬性,則會直接使用這個屬性的值,如果第一個對象中不存在名爲X的屬性,JavaScript會繼續查找鏈上的下一個對象。如果第二個對象依然沒有名爲X的屬性,則會繼續查找下一個對象,以此類推。如果作用域鏈上沒有任何一個對象含有屬性X,那麼就會認爲這段代碼的作用域鏈上不存在X,並最終拋出一個引用錯誤(ReferenceError)異常。

在JavaScript的最頂層代碼中(也就是不包含在任何函數定義內的代碼),作用域鏈由一個全局對象組成。在不包含嵌套的函數體內,作用域鏈上有兩個對象,第一個是定義函數參數和局部變量的對象,第二個是全局對象。在一個嵌套的函數體內,作用域鏈上至少有三個對象。理解對象鏈的創建規則是非常重要的。當定義一個函數時,它實際上保存一個作用域鏈,當調用這個函數時,它創建一個新的對象來存儲它的局部變量,並將這個對象添加至保存的那個作用域鏈,同時創建一個新的更長的表示函數調用作用域的鏈。對於嵌套函數來講,事情變得更有趣,每次調用外部函數時,內部函數都會重新定義一遍,因爲每次調用外部函數時,內部函數的代碼都是相同的。而且關聯這段代碼的作用域鏈也不相同

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章