閉包是學(xué)習(xí)javascript重點(diǎn),最初接觸到閉包時感覺到有點(diǎn)困難。當(dāng)然學(xué)習(xí)閉包也是非常重要一個環(huán)節(jié)。
- 詞法作用域
- 閉包
- 閉包模擬私有方法
1.詞法作用域
每個函數(shù)在創(chuàng)建時都會有個自己的環(huán)境,也就是詞法作用域。比如:
function f1 () {
var a = 1;
f2();
}
function f2 {
return a;
}
從上述代碼看出,我們分別創(chuàng)建兩個函數(shù)f1和f2
f1函數(shù)中 定義個局部變量a和 執(zhí)行f2函數(shù) 。f2函數(shù)里簡單的返回a的值 。
f1(); //a is not defined
因?yàn)閒1和f2函數(shù)只能訪問自身作用域和全局作用域里的內(nèi)容。所以f1函數(shù) 并不能訪問f2函數(shù)里的內(nèi)容 也就是說f1和f2函數(shù)不存在共享詞法作用域。
2.閉包
那么如何訪問到其他作用域里的內(nèi)容呢?
這時候就用閉包了
閉包是指那些能夠訪問獨(dú)立(自由)變量的函數(shù) (變量在本地使用,但定義在一個封閉的作用域中)
最常見創(chuàng)建閉包就是函數(shù)內(nèi)部再創(chuàng)建一個函數(shù),比如
function fn1() {
var name = "zhanglei";
function fn2() {
alert(name);
}
return fn2
}
var a = fn1();
a();
3.閉包模擬私有方法
JavaScript 可以使用閉包模擬私有方法。私有方法不僅僅有利于限制對代碼的訪問:還提供了管理全局命名空間的強(qiáng)大能力,避免非核心的方法弄亂了代碼的公共接口部分
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()); /* logs 0 */
Counter.increment();
Counter.increment();
console.log(Counter.value()); /* logs 2 */
Counter.decrement();
console.log(Counter.value()); /* logs 1 */
這里有個細(xì)節(jié)就是利用了全局命名空間,以避免非核心的方法弄亂了代碼的公共接口部分。
首先創(chuàng)建了一個自調(diào)函數(shù) 定義了一個私有變量和一個私有方法 然后返回了 三個公共函數(shù) 因?yàn)檫@三個公共函數(shù)是共享同一個環(huán)境的閉包。所以都可以訪問 privateCounter 變量和 changeBy 函數(shù)。