|
|
|
|
|
|
閉包是一個訪問其詞法范圍的函數,甚至在其詞法范圍之外執行。
更簡單地說,閉包是一個函數,它從定義它的地方記住變量,而不管它后來在哪里執行。在本文中,將通過多個示例介紹什么是閉包,及何時使用閉包。
JavaScript 閉包
在開始認識閉包之前,你得首先了解嵌套函數。
在 JavaScript 中,一個函數可以有一個或多個內部函數。這些嵌套函數在外部函數的范圍內。內部函數可以訪問外部函數的變量和參數。但是,外部函數不能訪問內部函數內部定義的變量。
function OuterFunction() {
var outerVariable = 1;
function InnerFunction() {
alert(outerVariable);
}
InnerFunction();
}在上面的例子中,InnerFunction() 可以訪問 outerVariable 這個變量。
現在,根據上面的定義,InnerFunction() 可以訪問 outerVariable 變量,即使它會單獨執行。參看以下示例。
function OuterFunction() {
var outerVariable = 100;
function InnerFunction() {
alert(outerVariable);
}
return InnerFunction;
}
var innerFunc = OuterFunction();
innerFunc(); // 100在上面的示例中,return InnerFunction; 當你調用 OuterFunction() 時,從 OuterFunction 返回 InnerFunction。變量innerFunc 僅引用 InnerFunction(),而不引用 OuterFunction()。所以現在,當你調用 innerFunc() 時,它仍然可以訪問outerVariable在 OuterFunction() 中聲明的內容,這稱為閉包。
一個函數可以在 JavaScript 中返回另一個函數,分配給變量的函數稱為函數表達式。
閉包的一個重要特征是外部變量可以在多次調用之間保持其狀態。請記住,內部函數不會保留外部變量的單獨副本,而是引用外部變量,這意味著外部變量的值將會改變,如果你使用內部函數更改它。示例:
function Counter() {
var counter = 0;
function IncreaseCounter() {
return counter += 1;
};
return IncreaseCounter;
}
var counter = Counter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
alert(counter()); // 4在上面的例子中,外部函數Counter返回內部函數IncreaseCounter()的引用。increaseCounter 將外部變量 counter 增加到 1。所以多次調用內部函數會使計數器每次增加一個。
閉包在多層內部函數中是有效的。示例:
function Counter() {
var counter = 0;
setTimeout( function () {
var innerCounter = 0;
counter += 1;
alert("counter = " + counter);
setTimeout( function () {
counter += 1;
innerCounter += 1;
alert("counter = " + counter + ", innerCounter = " + innerCounter)
}, 500);
}, 1000);
};
Counter();根據閉包的定義,如果內部函數訪問外部函數的變量,那么只有它被稱為閉包。
不是閉包的示例:
var Counter = (function () {
var i = 0;
return { counter : i += 1 };
})();何時使用閉包?
閉包對于隱藏 JavaScript 中的實現細節很有用。換句話說,創建私有變量或函數可能很有用。
以下示例顯示了如何創建私有函數和變量:
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
alert(counter.value()); // 0
counter.increment();
counter.increment();
alert(counter.value()); // 2
counter.decrement();
alert(counter.value()); // 1在上面的示例中,increment()、decrement() 和 value() 成為公共函數,因為它們包含在返回對象中,而 changeBy() 函數成為私有函數,因為它不返回并且僅在內部使用increment()和decrement()。
總結
本文通過多個示例,介紹了什么是閉包,以及何時使用閉包。通過本文的學習,你應該記住了閉包的一些重要特性,懂得判斷一些函數是不是閉包,不具備閉包特性的函數就不能稱之為閉包。
相關文章
