什么是閉包?相信很多人聽了有點懵,然后去百度查了一下官方的定義“閉包就是能夠讀取其他函數內部變量的函數”發現感覺自己更懵了。關于閉包如果只看那官方的定義的話確實不是讓人很容易理解。
要想理解什么是閉包,首先得弄清楚什么是作用域,作用域可以理解為一個變量可以使用的范圍。
在 JAVAScript 中有兩種作用域類型:
- 局部作用域
在 JavaScript 函數中聲明的變量會成為函數的局部變量。局部變量的作用域是局部的所以只能在函數內部訪問它們。
- 全局作用域
函數外聲明的變量屬于全局變量。全局變量的作用域是全局的所以網頁的任意部分和函數都能夠訪問它。
有了作用域做鋪墊,再來學習閉包就容易多了。
function f1(){
var n=10;//局部變量n
//在f1函數內部聲明的f2函數
function f2(){
alert(n);
}
return f2;//將f2函數作為f1函數的返回值
}
var fobj=f1();//f1調用完后的返回值是一個f2函數,此時fobj就是f2函數
fobj(); // 輸出10,調用f2函數
上述代碼就是一個簡單的閉包函數,閉包的用處有兩個,一個是可以讀取函數內部的變量,另一個就是在內存中讓這些變量的值始終保持。
function f1(){
var n=5;//局部變量n
add=function(){ //fdd前面沒有使用var關鍵字,因此add是一個全局變量的匿名函數
n+=1
}
//在f1函數內部聲明的f2函數
function f2(){
alert(n);
}
return f2;
}
var fadd=f1();
result(); // 輸出5
add();
fadd(); // 輸出6
從上面這段代碼中可以看出,fadd就是閉包f2函數。它一共運行了兩次,第一次的值是5,第二次的值是6。這證明函數f1中的局部變量n一直保存在內存中,并沒有在f1調用后被自動清除。因為f1是f2的父函數,而f2相當于賦給了f1一個全局變量,所以f2一直在內存中。而f2的存在又依賴于f1,因此f1也一直在內存中,不會在調用結束后回收。
由于閉包會使函數中的變量都被保存在內存中,導致內存消耗很大,造成網頁的性能問題,在IE中還可能導致內存泄露,所以不能濫用閉包,在退出函數之前,將不使用的局部變量全部刪除。