JS 閉包

「函數(shù)」和「函數(shù)內(nèi)部能訪問到的變量」的總和,就是一個(gè)閉包。
閉包的目的——隱藏變量
閉包常常用來「間接訪問一個(gè)變量」。換句話說,「隱藏一個(gè)變量」。

求下面函數(shù)的執(zhí)行結(jié)果

for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i)
  },0)
}

答案是:10個(gè)10,此題考查的就是JS的異步閉包

異步

JS是單線程的,即一次只能執(zhí)行一個(gè)命令,不能同時(shí)進(jìn)行多個(gè)命令。
JS的異步實(shí)現(xiàn):JS會(huì)在執(zhí)行時(shí)生成一個(gè)主任務(wù)隊(duì)列(M),所有的任務(wù)都會(huì)放進(jìn)M里面去排隊(duì)等待執(zhí)行,先進(jìn)去的先執(zhí)行。當(dāng)使用setTimeout時(shí),setTimeout會(huì)將里面的函數(shù)放到異步隊(duì)列中,當(dāng)前面的任務(wù)都執(zhí)行完成后,js通過eventloop事件循環(huán),發(fā)現(xiàn)異步列隊(duì)列中有任務(wù)在等待,于是將其添加到主隊(duì)列中開始執(zhí)行。

所以上面的代碼,實(shí)際上是for循環(huán)完成之后才會(huì)執(zhí)行setTimeout的function,而這個(gè)時(shí)候i的值是10,所以打印出來的都是10。

當(dāng)調(diào)用setTimeout( func, xx )的時(shí)候,JS引擎會(huì)啟動(dòng)定時(shí)器timer,大約 xx ms以后執(zhí)行 func,不過事實(shí)上,func 會(huì)在在瀏覽器不忙的時(shí)候才會(huì)真正執(zhí)行。

閉包

閉包(closure) 是Javascript語言的一個(gè)難點(diǎn),很多人說JS初級(jí)與高級(jí)工程師的分水嶺就在于對(duì)閉包的理解。

其實(shí)所有的JS函數(shù)都是閉包,只是在平時(shí)開發(fā)中,嵌套在函數(shù)內(nèi)的閉包更能發(fā)揮作用。

談閉包之前,先來談?wù)凧S變量的作用域:

  • 全局變量
var n=999;

function f1(){
  alert(n);
}

f1(); // 999

這里的 n 為全局變量,函數(shù)內(nèi)部可以讀取。

  • 局部變量
function f1(){
   var n = 999; // 局部變量一定要聲明,不能就變成全局變量了
}

alert(n) //  n is not defined

這里的 n 為局部變量,函數(shù)外部不能讀取。

那么,如果我們想要訪問和修改函數(shù)內(nèi)的局部變量,應(yīng)該怎么做呢?

那就是在函數(shù)的內(nèi)部,再定義一個(gè)函數(shù):

function f1() {
   var n = 999;
  
   function f2() {
      return n = n + 1
   };
   
   return f2;
}

var a = f1();
a(); // 1000
a(); // 1001
a(); // 1002

上述代碼中的 f2 就是閉包,可以看出,通過閉包,不僅可以訪問和修改函數(shù)內(nèi)部變量,還能使其一直存在內(nèi)存中,不被回收。

實(shí)現(xiàn)的原理:由于 f2 中引用了 相對(duì)于自己的全局變量 n ,所以 f2 會(huì)一直存在內(nèi)存中,又因?yàn)?n 是 f1 中的局部變量,也就是說 f2 依賴 f1,所以說 f1 也會(huì)一直存在內(nèi)存中,并不像普通函數(shù)那樣,調(diào)用后變量便被垃圾回收了。

所以說,在setTimeout中的函數(shù)引用了外層 for循環(huán)的變量 i,導(dǎo)致 i 一直存在內(nèi)存中,不被回收,所以等到JS隊(duì)列執(zhí)行 函數(shù)時(shí),i 已經(jīng)是 10了,所以最終打印 10個(gè)10。

本文參考:一道經(jīng)典JS面試題(閉包+異步)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容