什么是閉包?作用?
函數與對其狀態(tài)即詞法環(huán)境(lexical environment)的引用共同構成閉包(closure)。也就是說,閉包可以讓你從內部函數訪問外部函數作用域。在JavaScript,函數在每次創(chuàng)建時生成閉包。
閉包常常用來間接訪問一個變量
1.閉包
閉包是由函數以及創(chuàng)建該函數的詞法環(huán)境組合而成。這個環(huán)境包含了這個閉包創(chuàng)建時所能訪問的所有局部變量。
function makeFunc() {
var name = "Mozilla";
return function displayName() {
return name;
}
}
var myFunc = makeFunc(); //myFunc 就是個閉包
console.log(myFunc()); // Mozilla
2.閉包簡單使用
在面向對象編程中,對象允許我們將某些數據(對象的屬性)與一個或者多個方法相關聯。
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
console.log(Counter.value()); // 0
Counter.increment();
Counter.increment();
console.log(Counter.value()); //2
Counter.decrement();
console.log(Counter.value()); //1
3.在循環(huán)中創(chuàng)建閉包:一個常見錯誤
循環(huán)早已執(zhí)行完畢,arr ( 被三個閉包所共享)arr[0]已經等于了 arr的最后一項的值
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]()); //2
解決方法以下
方案一:使用更多的閉包
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = makeCallback(i)
}
return arr;
}
var bar = foo();
console.log(bar[0]()); //0
function makeCallback(i) {
return function(){
return i;
}
}
方案二:避免使用過多的閉包,可以用let關鍵詞
function foo(){
var arr = [];
for(let i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]()); //0
- 性能考量
如果不是某些特定任務需要使用閉包,在其它函數中創(chuàng)建函數是不明智的,因為閉包在處理速度和內存消耗方面對腳本性能具有負面影響。
- 可以用閉包模擬私有方法
比如 Java,是支持將方法聲明為私有的,即它們只能被同一個類中的其它方法所調用。而 JavaScript 沒有這種原生支持,但我們可以使用閉包來模擬私有方法。具體見https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
參考網頁:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
https://zhuanlan.zhihu.com/p/22486908