首先咱們要知道javascript語言,它是基於詞法做用域的語言(簡單的來講就是經過閱讀包含變量在內的數行代碼就能知道變量的做用域)全局變量在程序中始終是有定義的,局部變量在聲明他的函數體內以及其所嵌套的函數內始終是有定義的javascript
假如咱們把局部變量換個角度來考慮,把它當作自定義實現對象的屬性,那麼咱們就能夠換個角度來解讀變量的做用域。java
每一段javascript代碼(全局代碼或函數)都有一個與之關聯的做用域鏈(scope chain)其實這個做用域鏈是一個對象列表,或者是鏈表。 這組對象定義了這個這段代碼的 「做用域中的變量」,當javascript須要查找到變量x的值的時候(這個過程叫作變量的解析) 他會從鏈的第一個對象開始查找,若是這個對象有一個名爲x的屬性,則會直接使用這個x的屬性。若是第一個對象沒有x屬性 則會以此類推 查找下一個。若果整個做用域鏈上都沒有這個屬性,最後會拋出一個引用錯誤(ReferenceError)函數
在javascript中最頂層的代碼中(注:就是不包含任何函數函數定義內的代碼);做用域鏈由一個全局對象組成,在不包含嵌套的函數體內,做用域鏈上有兩個對象。spa
第一個是定義函數參數和局部變量的對象,第二個是全局變量。須要注意的是在一個嵌套的函數內,做用域鏈上至少有三個對象對象
理解對象原型鏈的建立規則:ip
當定義一個函數時,其實是保存了一個做用域鏈,當調用這個行數時,它建立一個對象來保存存儲它的局部變量,並將這個對象添加到保存的那個做用域鏈上,同時建立一個新的更長的函數調用做用域鏈原型鏈
對於嵌套函數來講,每次調用外部函數,內部函數都會被從新定義一遍,由於每次調用外部函數時內部函數都會被從新定義一次。由於每次調用外部函數時做用域鏈都是不一樣的。作用域