2020-04-20 JS閉包

閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。

閉包的作用:
  1. 可以在函數(shù)的外部訪問到函數(shù)內(nèi)部的局部變量。
  2. 讓這些變量始終保存在內(nèi)存中,不會隨著函數(shù)的結(jié)束而自動銷毀。

我們想在一個函數(shù)內(nèi)部也有限權(quán)訪問另一個函數(shù)內(nèi)部的變量該怎么辦呢?閉包就是用來解決這一需求的,閉包的本質(zhì)就是在一個函數(shù)內(nèi)部創(chuàng)建另一個函數(shù)。
我們首先知道閉包有3個特性:
①函數(shù)嵌套函數(shù)
②函數(shù)內(nèi)部可以引用函數(shù)外部的參數(shù)和變量
③參數(shù)和變量不會被垃圾回收機制回收
本文我們以閉包兩種的主要形式來學習

一個閉包簡單的例子
function a(){
  var name = 'sll';
  return function(){
    return name;
  }
}
var b = a();
console.log(b())

a()中的返回值是一個匿名函數(shù),這個函數(shù)在a()作用域內(nèi)部,所以它可以獲取a()作用域下變量name的值,將這個值作為返回值賦給全局作用域下的變量b,實現(xiàn)了在全局變量下獲取到局部變量中的變量的值

一個經(jīng)典的閉包例子
function fn(){
  var num = 3
  return function(){
    var n = 0
    console.log(++n)
    console.log(++num)
  }
}
var fn1 = fn()
fn1() //(1,4)
fn1() //(1,5)

一般情況下,在函數(shù)fn執(zhí)行完后,就應(yīng)該連同它里面的變量一同被銷毀,但是在這個例子中,匿名函數(shù)作為fn的返回值被賦值給了fn1,這時候相當于fn1=function(){var n = 0 … },并且匿名函數(shù)內(nèi)部引用著fn里的變量num,所以變量num無法被銷毀,而變量n是每次被調(diào)用時新創(chuàng)建的,所以每次fn1執(zhí)行完后它就把屬于自己的變量連同自己一起銷毀,于是乎最后就剩下孤零零的num,于是這里就產(chǎn)生了內(nèi)存消耗的問題

再來看一個經(jīng)典例子-定時器與閉包

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

按照預(yù)期它應(yīng)該依次輸出1 2 3 4 5,而結(jié)果它輸出了五次5,這是為什么呢?原來由于js是單線程的,所以在執(zhí)行for循環(huán)的時候定時器setTimeout被安排到任務(wù)隊列中排隊等待執(zhí)行,而在等待過程中for循環(huán)就已經(jīng)在執(zhí)行,等到setTimeout可以執(zhí)行的時候,for循環(huán)已經(jīng)結(jié)束,i的值也已經(jīng)變成5,所以打印出來五個5,那么我們?yōu)榱藢崿F(xiàn)預(yù)期結(jié)果應(yīng)該怎么改這段代碼呢?(ps:如果把for循環(huán)里面的var變成let,也能實現(xiàn)預(yù)期結(jié)果)

for (var i = 0; i < 5; i++) {

    (function(i){
        setTimeout( ()=>{
            console.log(i)  
        },100)
    })(i)
}

最后總結(jié)一下閉包的好處與壞處

好處
①保護函數(shù)內(nèi)的變量安全 ,實現(xiàn)封裝,防止變量流入其他環(huán)境發(fā)生命名沖突
②在內(nèi)存中維持一個變量,可以做緩存(但使用多了同時也是一項缺點,消耗內(nèi)存)
③匿名自執(zhí)行函數(shù)可以減少內(nèi)存消耗

壞處
①被引用的私有變量不能被銷毀,增大了內(nèi)存消耗,造成內(nèi)存泄漏,解決方法是可以在使用完變量后手動為它賦值為null;
②其次由于閉包涉及跨域訪問,所以會導(dǎo)致性能損失,我們可以通過把跨作用域變量存儲在局部變量中,然后直接訪問局部變量,來減輕對執(zhí)行速度的影響

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

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

  • 前言 面試問題: 說一下對變量提升的理解 說明this的幾種不同的使用場景 創(chuàng)建10個 標簽,點擊的時候彈出來對應(yīng)...
    陳觀齊閱讀 325評論 0 1
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 3,150評論 2 9
  • 1.什么是閉包? 要了解什么是閉包,首先你要了解作用域。 js的作用域分兩種,全局作用域和局部作用域。 我們知道在...
    zhudying閱讀 443評論 0 1
  • 前言: 看過一些相關(guān)文章,知道想理解閉包,詞法作用域和作用域(鏈)是非常重要的前置知識,結(jié)合之前所學,可以繼續(xù)學習...
    饑人谷_遠方閱讀 306評論 0 0
  • 平凡·原創(chuàng) 今天,被兩個年輕人傷到了。 我們是一個團隊,一塊運行一個文學社團。我算是負責人吧。因為這個社團已經(jīng)運行...
    平凡之梅閱讀 175評論 0 2

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