閉包再深入

一直對閉包這個概念模糊不清,今天搗鼓半天,大致理通了。
閉包是什么?

有權訪問另外一個函數(shù)作用域中的變量的函數(shù)。

一般來講,作用域是由函數(shù)創(chuàng)建的(這里我們只討論函數(shù)作用域,不涉及ES6之后的塊級作用域)。每個函數(shù)的作用域都是封閉的,外部是無法訪問函數(shù)作用域中的變量。
那有沒有辦法可以從外部訪問到函數(shù)內部的變量呢
答案是有的,通過嵌套函數(shù)的方式,見下面的示例。

function change(){
    var a = 1
    function plus(){
        a++
        console.log(a)
    }
    return plus
}
var final = change()
final() //2
final() //3
final() //4

在該例中,我們得增加點知識點:

  • 函數(shù)的作用域
  • 變量的生命周期

plus函數(shù)作用域內沒有變量a,依據(jù)作用域鏈,找到父作用域中的變量a,當執(zhí)行final()時,a++,a=2。再執(zhí)行final()時,結果依然+1。
這里有點困惑,變量的生命周期起始于函數(shù)執(zhí)行時,終止于函數(shù)執(zhí)行完畢,為什么這里面函數(shù)中的變量a未被回收,數(shù)值一直遞增。
原因在于變量a被函數(shù)plus引用,final()間接引用著變量a。導致變量a未被內存回收。
閉包最大的用處在于:暴露局部變量,保持變量在內存中不被回收。
再來看些經典的閉包題來理解下思路

for(var i = 1; i< 10; i++){
    function a(){
    console.log(i)
    }
} 
a() //10

為什么得到10,很簡單。for循環(huán)中是函數(shù)表達式,當循環(huán)結束后,執(zhí)行a(),其中的i不存在按作用域鏈找到上一級的i并引用,結果為10。
怎么讓其按我們設想的0,1,2...輸出呢?
也很簡單,每次循環(huán)執(zhí)行一次函數(shù),傳參,var a = i ,運用立即執(zhí)行函數(shù),見下

for(var i = 1; i< 10; i++){
    !function a(a){
    console.log(a)
    }(i)
} 

如果糾結0~9,和輸出來為什么是10,可以參考下for循環(huán)的執(zhí)行次序

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容