標籤:
範圍即變數和函數的可存取範圍。在js中,範圍包括全域範圍和局部範圍。
1 變數範圍
在函數體內,局部變數的優先順序高於同名的全域變數。如果在函數內聲明的一個局部變數或者函數參數中帶有的變數和全域變數重名,那麼全域變數就被局部變數所遮蓋。
聲明局部變數必須用var語句。
2 函數範圍(function scope)和聲明提前(hoisting)
變數在聲明它們的函數體以及這個函數體嵌套的任意函數體內都是有定義的。
1 var scope="global";2 function f(){3 console.log(scope);//輸出“undefined”而不是”global“4 var scope ="local"; 5 console.log(scope);//輸出local 6 }
javascript函數裡聲明的所有變數(不涉及賦值)都被”提前“至函數體的頂部,同時變數初始化留在原來的位置,這個特性被稱為聲明提前(hoisting)。所以上述過程等價於
1 var scope="global";2 function f(){3 var scope;4 console.log(scope);//輸出“undefined”而不是”global“5 scope ="local"; 6 console.log(scope);//輸出local 7 }
在函數體內,局部變臉scope將覆蓋全域變數中定義的scope,但並未對其賦值,所以輸出為undefined.
3 範圍鏈
當聲明一個javascript全域變數時,實際上是定義了一個全域對象的一個屬性。局部變數是和函數調用相關的某個對象的屬性。
每一段javascript代碼(全域代碼或函數)都有一個與之關聯的範圍鏈(scope chain)。這個範圍鏈是一個對象列表或鏈表,這組對象定義了這段代碼”範圍中“的變數。當javascript需要尋找變數X時(即變數解析),它會從鏈中的第一個對象開始尋找,如果這個對象有一個名為x的屬性,則會直接使用這個屬性值,如果第一個對象中不存在,則繼續尋找鏈上的下一個對象,以此類推。如果沒有,則最終拋出一個引用錯誤(ReferenceError)異常。
對象鏈的建立規則:當定義一個函數時,儲存一個範圍鏈。調用這個函數時,建立一個新的對象儲存它的局部變數,並添加這個對象到新儲存的範圍鏈上。
對於嵌套函數來說,每次調用外部函數時,內建函式又會重新定義一遍。
JavaScript範圍學習筆記