Javascript中閉包(Closure)的探索(一)-基本概念
由于我是做web開發的,在項目中經常使用javascript。對js的閉包特性早有耳聞,趁著不是很忙自己研究了一下。
通過從網絡上的查找,了解到javascript的閉包特性,總結了一下,不足之處希望大家不吝指教!
1.Closure的基本概念(摘抄如下):
“閉包”是一個表達式(一般是函數),它具有自由變量以及綁定這些變量的環境(該環境“封閉了”這個表達式)。
閉包,就是封閉了外部函數作用域中變量的內部函數。但是,如果外部函數不返回這個內部函數,閉包的特性無法顯現。
如果外部函數返回這個內部函數,那么返回的內部函數就成了名副其實的閉包。此時,閉包封閉的外部變量就是自由變量,而由于該自由變量存在,外部函數即便返回,其占用的內存也得不到釋放。
2.以一個小問題為例解釋一下閉包的特性:
要求:給頁面上的一系列按鈕綁定帶有不同參數的函數。
代碼(為說明問題簡化了代碼):
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>JsClosure</title>
<script type="text/javascript">
function initBtnClick() {
for (var i = 1; i < 6; i++) {
var btn = document.getElementById("button" + i);
btn.onclick = function() {
alert(i);
};
}
}
</script>
</head>
<body>
<input type="button" value="closureTest" onclick="initBtnClick()" />
<input type="button" value="button1" id="button1" />
<input type="button" value="button2" id="button2" />
<input type="button" value="button3" id="button3" />
<input type="button" value="button4" id="button4" />
<input type="button" value="button5" id="button5" />
</body>
</html>
現象:首先點擊“closureTest”按鈕給其他按鈕綁定事件,然后點擊其他五個按鈕發現alert出來的值全是6。與預期的1,2,3,4,5相差甚遠!
按閉包的定義分析現象:在給按鈕綁定事件時使用的匿名函數(即封閉了外部函數作用域中變量的內部函數),但是由于外部函數initBtnClick沒有返回此匿名函數,所以閉包沒有起作用(即如果外部函數不返回這個內部函數,閉包的特性無法顯現)。匿名函數封閉的外部變量(即i)沒有成為自由變量,內存被釋放,最終只保留了循環的最后一個值6。
根據分析改進initBtnClick函數,使其形成一個真正的閉包:
function initBtnClick() {
for (var i = 1; i < 6; i++) {
var btn = document.getElementById("button" + i);
btn.onclick = function(j) {
return function() {
alert(j);
}
} (i);
}
}
再次點擊“closureTest”按鈕給其他按鈕綁定事件,然后點擊其他五個按鈕發現依次alert1,2,3,4,5。與預期的結果相同。
現象分析:通過執行外部的匿名函數(function(j))返回內部的匿名函數function(){alert(j);}形成真正的閉包(即如果外部函數返回這個內部函數,那么返回的內部函數就成了名副其實的閉包)。匿名函數(function(j))傳入的參數i就成了自由變量,內存不會被釋放(即閉包封閉的外部變量就是自由變量,而由于該自由變量存在,外部函數即便返回,其占用的內存也得不到釋放)。
改進后的代碼如下,為了清晰一些將內部匿名函數封裝了一下:
function displayNum(inputNum) {
return function() {
alert(inputNum);
};
}
function initBtnClick() {
for (var i = 1; i < 6; i++) {
var btn = document.getElementById("button" + i);
btn.onclick = displayNum(i);
}
}
本例只是簡單的介紹了一下js的閉包,只是希望大家能對閉包有個直觀點的了解。

浙公網安備 33010602011771號