JavaScript是基于詞法作用域的語言:通過閱讀包含變數定義在內的數行原始碼就能知道變數的作用域,全域變數在程式中始終都是有定義的,區域變數在宣告它的函式體內以及其所嵌套的函式內始終是有定義的,
如果將一個區域變數看做是自定義實作的物件的屬性的話,那么可以換個角度來解讀變數作用域,每一段JavaScript代碼(全域代碼或函式)都有一個與之關聯的作用域鏈(scope chain),這個作用域鏈是一個物件串列或者鏈表,這組物件定義了這段代碼“作用域中”的變數,當JavaScript需要查找變數x的值的時候(這個程序稱做“變數決議”(variable resolution)),它會從鏈中的第一個物件開始查找,如果這個物件有一個名為x的屬性,則會直接使用這個屬性的值,如果第一個物件中不存在名為x的屬性,JavaScript會繼續查找鏈上的下一個物件,如果第二個物件依然沒有名為x的屬性,則會繼續查找下一個物件,以此類推,如果作用域鏈上沒有任何一個物件含有屬性x,那么就認為這段代碼的作用域鏈上不存在x,并最終拋出一個參考錯誤(ReferenceError)例外,
在JavaScript的最頂層代碼中(也就是不包含在任何函式定義內的代碼),作用域鏈由一個全域物件組成,在不包含嵌套的函式體內,作用域鏈上有兩個物件,第一個是定義函式引數和區域變數的物件,第二個是全域物件, 在一個嵌套的函式體內,作用域鏈上至少有三個物件,理解物件鏈的創建規則是非常重要的,當定義一個函式時,它實際上保存一個作用域鏈,當呼叫這個函式時,它創建一個新的物件來存盤它的區域變數,并將這個物件添加至保存的那個作用域鏈上,同時創建一個新的更長的表示函式呼叫作用域的“鏈”,對于嵌套函式來講,事情變得更加有趣,每次呼叫外部函式時,內部函式又會重新定義一遍, 因為每次呼叫外部函式的時候,作用域鏈都是不同的,內部函式在每次定義的時候都有微妙的差別——在每次呼叫外部函式時,內部函式的代碼都是相同的,而且關聯這段代碼的作用域鏈也不相同,
作用域鏈的概念對于理解with陳述句(見5.7.1節)是非常有幫助的,同樣對理解閉包(見8.6節)的概念也至關重要,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/83642.html
標籤:JavaScript
上一篇:選單制作:ul li橫向排列
