JavaScript作用域分為全域作用域和局部作用域兩類。變數在函數外定義為全域變量,全域變數有全域作用域,即網頁中的所有腳本和函數均可使用;變數在函數內部宣告為局部作用域,局部作用域一般只在固定的程式碼片段(例函數)內部可存取。
本教學操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。
變數的作用域(scope),指的是變數在腳本程式碼中的可讀、寫的有效範圍,也就是腳本程式碼中可以使用這個變數的區域。
變數的作用域主要分為全域作用域、局部作用域(也稱為函數作用域)兩種。
對應作用域的變數分別稱為全域變數、局部變數。全域變數宣告在所有函數之外;局部變數是在函數體內宣告的變數或是函數的命名參數。
全域作用域(Global Scope)
變數在函數外定義為全域變量,全域變數有全域作用域:網頁中的所有腳本和函數皆可使用。
在程式碼中任何地方都能存取的物件擁有全域作用域,一般來說以下幾種情形擁有全域作用域:
1、最外層函數和在最外層函數外面定義的變數擁有全域作用域
2、所有末定義直接賦值的變數自動宣告為擁有全域作用域
3、所有window物件的屬性擁有全域作用域
一般情況下,window物件的內建屬性都擁有全域作用域,例如window.name、window.location、window.top等等。
局部作用域(Local Scope)
變數在函數內部宣告為局部作用域。
和全域作用域相反,局部作用域一般只在固定的程式碼片段(例:函數)內部可存取到,最常見的例如函數內部,所有在一些地方也會看到有人把這種作用域稱為函數作用域。
總之呢,當JS解析器執行時,首先就會在執行環境裡建構一個全域對象,我們定義的全域屬性就是做為該對象的屬性讀取,在頂層程式碼中我們使用this關鍵字和window物件都可以存取到它。
而函數體中的局部變數只在函數執行時產生的呼叫物件中存在,函數執行完畢時局部變數即刻銷毀。
因此在程式設計中我們需要考慮如何合理宣告變量,這樣既減小了不必要的記憶體開銷,同時能很大程度地避免變數重複定義而覆寫先前定義的變數所造成的Debug麻煩。
說明:
變數的作用域跟宣告方式有著密切的關係。使用 var 宣告的變數的作用域有全域作用域和函數作用域;使用 let 和 const 宣告的變數有全域作用域、局部作用域。
注意:嚴格意義的全域變數都屬於window 物件的屬性,但let 和const 宣告的變數並不屬於window 對象,所以它們並不是嚴格意義上的全域變量,在此僅從它們的作用域這個角度來說它們是全域變數的。
由於var 支援變數提升,所以var 變數的全域作用域是對整個頁面的腳本程式碼有效;而let 和const 不支援變數提升,所以let 和const 變數的全域作用域指的是從宣告語句開始到整個頁面的腳本程式碼結束之間的整個區域,而宣告語句之前的區域是沒有效的。
同樣,因為var 支援變數提升,而let 和const 不支援變數提升,所以使用var 宣告的局部變數在整個函數中有效,而使用let 和const 宣告的局部變數從宣告語句開始到函數結束之間的區域有效。需要注意的是,如果局部變數和全域變數同名,則在函數作用域中,局部變數會履蓋全域變量,即在函數體中起作用的是局部變數;在函數體外,全域變數起作用,局部變數無效,此時引用局部變數將出現語法錯誤。
範例:變數的作用域
var v1 = "JavaScript"; //全局变量 let v2 = "JScript"; //全局变量 let v3 = "Script"; //全局变量 scopeTest(); //调用函数 function scopeTest(){ var lv = "aaa"; //局部变量 var v1 = "bbb"; //局部变量 let v2 = "ccc"; //局部变量 console.log("函数体内输出的lv = " + lv); //aaa console.log("函数体内输出的v1 = " + v1); //bbb console.log("函数体内输出的v2 = " + v2); //ccc console.log("函数体内输出的v3 = " + v3); //Script //v4为全局变量,赋值在后面,因而值为undefined console.log("函数体内输出的v4 = " + v4); } var v4 = "VBScript"; //全局变量 console.log("函数体外输出的lv = " + lv); //① 报ReferenceError错误 console.log("函数体外输出的v1 = " + v1); //JavaScript console.log("函数体外输出的v2 = " + v2); //JScript console.log("函数体外输出的v3 = " + v3); //Script console.log("函数体外输出的v3 = " + v4); //VBScript
上述腳本程式碼分別宣告了 4 個全域變數、3 個局部變數。在 scopeTest 函數體外,變數 v1、v2、v3 和 v4 為全域變數;在 scopeTest 函數體內,lv、v2是全域變數。
我們看到,局部變數v1 和v2 與全域變數v1 和v2 同名,在scopeTest 函數體內,局部變數v1 和v2 有效,因而在函數體這2 個變數的輸出結果分別為「bbb 」和「ccc」;在函數體外,全域變數v1 和v2 有效,因而在函數體外,這2 個變數的輸出結果分別為「JavaScript」和「JScript」。
另外,全域變數v3 和v4 在函數體內沒有被覆蓋,因而輸出的是全域變數的值,所以v3 在函數體內和體外的輸出結果都為“Script”,而v4 變數的賦值在函數呼叫的後面,因而在函數體中的v4 輸出結果為“undefined”,而在函數體外的輸出是在宣告之後,所以結果為“VBScript”。 lv 是局部變量,因而在函數體外存取會報「ReferenceError」錯誤。
上述程式碼在Chrome 瀏覽器中運作後,開啟瀏覽器的控制台,可以看到下圖所示的輸出結果
上圖所示報第18 行程式碼(即範例① 處註解的程式碼)中的lv 沒有定義的參考錯誤,這是因為lv 變數為局部變量,離開函數後無效。將這行程式碼註解後再運行,此時開啟瀏覽器控制台可看到下圖所示結果
#【推薦學習:javascript高階教學】
以上是JavaScript作用域分為哪兩類的詳細內容。更多資訊請關注PHP中文網其他相關文章!