1.啥是閉包?
閉包是一個函數,一個能夠讀取某函數內部變量的一個函數。
2.閉包有啥用途?
通過閉包可以讀取某函數的內部變量,相當於擴大了變量的訪問範圍;
3.閉包舉例
示例1
function add(num1,num2){
var innerAdd = function(){
alert(num1+num2);
}
return innerAdd;
}
//客戶端:
$(function(){
var innerAdd = add(1,2);
setTimeout(innerAdd,5000);
var innerAdd = add(2,2);
setTimeout(innerAdd,5000);
});
</script>
innerAdd 是一個閉包,它延長了變量num1、num2的生命時間;
注意,此時的num1、num2是形參哈;
示例2
<script type="text/javascript">
$(function(){
/*************** 給每個span元素追加點擊事件 ****************/
//test1
var spans = $("#divTest span");
for (var i = 0; i < spans.length; i++) {
var clickFunction = function() {
alert(i);
};
spans[i].onclick = clickFunction;
}
//test2
var spans = $("#divTest span");
for (var i = 0; i < spans.length; i++) {
function out(num){
var clickFunction = function() {
alert(num);
};
return clickFunction;
}
spans[i].onclick = out(i);
}
});
</script>
--------------------------------------
<body>
<div id="divTest" >
<span>0</span> <BR/>
<span>1</span> <BR/>
<span>2</span> <BR/>
<span>3</span> <BR/>
</div>
</body>
test1結果:
每次都是4。原因分析:
clickFunction 是一個閉包,它延長的是變量 i 的生命時間。注意,此時的 i 可不是形參哈。
當i的值爲4的時候,判斷條件不成立,for循環執行完畢。但是因爲每個span的onclick方法這時候爲內部函數,所以i被閉包引用,內存不能被銷燬,i的值會一直保持4。直到程序改變i的值或者所有的onclick函數銷燬(主動把函數賦爲null或者頁面卸載)時纔會被回收。這樣每次我們點擊span的時候,onclick函數會查找i的值(作用域鏈是引用方式),一查等於4,然後就alert給我們了。
也就是說,當for循環執行完畢,此時的 i = 4;由於閉包延長了 i 的生命時間,所以在內存中,i =4 一直存在着。當點擊事件觸發時,會彈出4.
test2結果:
分別是1,2,3,4。原因分析:
clickFunction 是一個閉包,它延長的是變量 num 的生命時間,並不是變量 i 。
每次調用out函數,都會新創建一個新的out函數的作用域空間。所以閉包延長的是當前變量 num 的生命時間。注意,此時的 num 是形參,這個形參的值來自於 i 。
從本質上講,如果內部函數引用了位於外部函數中的變量,相當於授權該變量能夠被延遲使用。因此,當外部函數調用完成後,這些變量的內存不會被釋放(最後的值會保存),閉包仍然需要使用它們。