一、js變數作用域
js的變數作用域有兩種,全域性變數和區域性變數
需要注意的是,函式內部可以直接讀取全域性變數。
var global = 666;
function func() {
alert(global);
}
func(); //666
複製程式碼
函式外部無法讀取到函式內部的區域性變數,因為函式在執行完之後,函式內部的環境就被銷燬了。
function func() {
var message = 888;
}
alert(message); // error
複製程式碼
如果函式內部沒有使用var
,那麼實際上就相當於把這個變數宣告為全域性變數了。
function func() {
message = 999;
}
func(); //這裡注意要執行一遍函式,`message` 才有定義
alert(message);
複製程式碼
二、如何從外部讀取到區域性變數?
function f1() {
var message = 999;
function f2() {
alert(message); //999
}
}
複製程式碼
上面的程式碼中,f2
可以訪問到f1
的區域性變數message
,那麼我們只要把f2
作為f1
的返回值return
出去,那麼就可以在外部訪問到message
了。
function f1() {
var message = 999;
function f2() {
alert(message); //999
}
return f2;
}
複製程式碼
三、簡單理解閉包
上面的f2
函式就是閉包。
閉包就是能夠讀取其他函式內部變數的函式,所以,閉包實際上是一個函式。
閉包可以理解為“定義在一個函式內部的函式”,本質上,閉包是將函式內部和外部連線起來的一座橋樑。
這裡要注意一點,父函式內部定義的子函式,如果沒有引用父函式作用域中的變數,那麼這個子函式不是閉包,這點非常重要,也就是說,閉包是由函式和它所在的環境構成的,缺一不可。
四、 閉包的用途
1.讀取函式內部的變數 2.讓這些變數始終儲存在記憶體中
function f1() {
var n = 999;
nAdd = function() { n += 1 }; //nAdd是一個全域性函式
function f2() {
alert(n);
}
return f2;
}
var result = f1(); //result是一個函式,f1中return的字函式
result();//999
nAdd();//執行全域性函式
result();//1000
複製程式碼
理解:按照正常的函式執行,f1
執行完了之後,f1
的變數n
會被銷燬,但是上面的n
仍然保留著999的數值,原因是f1
的返回值f2
被賦值給全域性變數result
, 而f2
的存在依賴f1
,所以f1
也一直在記憶體中。
五、使用閉包的注意事項
閉包會讓函式中的變數都被儲存在記憶體中,記憶體消耗大,所以不能濫用閉包,可以在不使用該變數的時候將其delete。
閉包會在父函式外部改變父函式內部的值,如果把父函式當作object使用,把閉包當作公有方法,內部變數當作私有成員,那就要小心不要隨意改變父函式內部變數的值。
參考資料: