之前我寫過一篇JavaScript原型與原型鏈的文章肮塞,此屬于JS中的重難點(diǎn)逾一。
而閉包几蜻,是JS中除了原型鏈之外又一個(gè)重點(diǎn)和難點(diǎn)。
一体斩、何為閉包
所謂“閉包”梭稚,指的是一個(gè)擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個(gè)函數(shù)),因而這些變量也是該表達(dá)式的一部分絮吵。
以上是比較官方的解釋弧烤,但是感覺晦澀難懂(反正我是沒怎么看懂),按照我的理解其實(shí)就是函數(shù)蹬敲,具體點(diǎn)就是在函數(shù)內(nèi)部定義的函數(shù)暇昂,但是就只是這么一說也太不負(fù)責(zé)任了,我們還是具體以實(shí)例來簡(jiǎn)單理解閉包吧伴嗡。
function a(n,m){
var bb = 10;
return function(){ // 閉包
console.log(bb); // 10
return n+m;
}
}
var sum = a(1,2)();
console.log(sum); // 3
上面這個(gè)例子中急波,a()函數(shù)中返回的這個(gè)匿名函數(shù)就是閉包,而閉包的一個(gè)作用就是能夠訪問外部包含它的函數(shù)內(nèi)的變量瘪校。
二澄暮、閉包與變量問題
function createFunction(){
var result = [];
for(var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
表面上看這個(gè)函數(shù)沒有什么問題,應(yīng)該可以正確地返回一個(gè)包含10個(gè)函數(shù)的數(shù)組阱扬,而每個(gè)函數(shù)都會(huì)返回自己的索引值泣懊。然而實(shí)際上并不是這樣的,實(shí)際上所有閉包的返回結(jié)果都是10麻惶。
console.log(createFunction()[0]()); // 10
console.log(createFunction()[9]()); // 10
這是因?yàn)殚]包只能取得包含函數(shù)中任何變量的最后一個(gè)值馍刮,那如果要實(shí)現(xiàn)上面返回相應(yīng)索引值應(yīng)該怎么修改呢?
三窃蹋、如何解決問題
① 使用立即執(zhí)行的匿名函數(shù)
修改后的代碼如下:
function createFunction() {
var result = [];
for(var i = 0; i < 10; i++) {
result[i] = function(num) {
return function() {
return num;
};
}(i);
}
return result;
}
console.log(createFunction()[0]()); // 0
console.log(createFunction()[9]()); // 9
修改后的代碼使用了一個(gè)立即執(zhí)行匿名函數(shù)卡啰,這個(gè)匿名函數(shù)能夠在每個(gè)循環(huán)中獲取相應(yīng)的變量i并作為其參數(shù)傳遞給num并立即執(zhí)行函數(shù),那么最終返回的那個(gè)num變量自然就是遞增的 i脐彩。
② 使用ES6中的let關(guān)鍵字來定義變量 i
修改后的代碼如下:
function createFunction(){
var result = [];
for(let i = 0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
此方法雖然簡(jiǎn)單碎乃,但是目前瀏覽器對(duì)ES6語法兼容性并不好,所以還是建議使用方法①惠奸。
結(jié)束語: 本人對(duì)于JS閉包理解其實(shí)也并不是很透徹梅誓,如果有不足之處,還請(qǐng)多多指正,謝謝梗掰!