簡單的聊一下閉包

js中的閉包

閉包是學(xué)習(xí)js中永遠(yuǎn)也繞不過去的一個坎,那么,今天我們就去一段簡單的代碼開始聊一聊閉包

什么是閉包

這個概念性的東西翻譯有很多種,純官方的翻譯比較晦澀難懂,我們把它理解成一個比較特殊的函數(shù)就行。按照網(wǎng)上的說法來說就是:

「函數(shù)」和「函數(shù)內(nèi)部能訪問到的變量」(也叫環(huán)境)的總和,就是一個閉包。

  function close() {
        var n=999;
        var getNumber=function () {
            return n;
        };
        return getNumber;
    }

在close函數(shù)里面有一個getNumber方法,通過getNumber方法可以訪問到函數(shù)的內(nèi)部變量。

閉包的特性

  • 能夠讀取函數(shù)內(nèi)部的變量
  • 能讓這些變量的值始終保持在內(nèi)存中

第一點(diǎn)很好理解,我們平時可能在不知不覺中就使用了閉包的這個特性,而第二點(diǎn)雖然用的不多,但是在面試中經(jīng)常遇到。首先我們先看一段代碼:

 function f1() {
        var n=999;
        nAdd=function () {
            n++;
        };
        function f2() {
            console.log(n);
        }
        return f2;
    }
    var result=f1();
    result();//999
    nAdd();
    result();//1000

為什么第二次執(zhí)行后打印的結(jié)果是1000,而不是999,因?yàn)閚被保存下來了,并沒有被內(nèi)存回收機(jī)制回收。

為什么每有被回收?因?yàn)閒1是f2的父函數(shù),而f2被賦給了一個全局變量,這導(dǎo)致f2始終在內(nèi)存中,而f2的存在依賴于f1,因此f1也始終在內(nèi)存中,不會在調(diào)用結(jié)束后,被垃圾回收機(jī)制(garbage collection)回收。

面試題解讀

這是一個很常見的閉包面試題:

    var result=[];
    function foo(){
        var i= 0;
        for (;i<3;i=i+1){
            result[i]=function () {
                alert(i);
            }
        }
    }         
    foo();
    result[0](); // 3
    result[1](); // 3
    result[2](); // 3

運(yùn)行結(jié)果為什么是3,我簡單的重現(xiàn)一下代碼運(yùn)行的過程,

i=0;
result[0]=function(){alert(i)};
i=1;
result[1]=function(){alert(i)};
i=2;
result[2]=function(){alert(i)};

運(yùn)行的時候在function內(nèi)部放的是一個變量i,只有被執(zhí)行的時候才會給這個i賦值。當(dāng)執(zhí)行result[0]的時候,里面的變量i因?yàn)樵诋?dāng)前作用域下并沒有被定義,所以向它的父級去找,此時for循環(huán)已經(jīng)執(zhí)行完畢,i的值是3,所以彈出的都是3。為什么i保存下來了,因?yàn)閞esult函數(shù)依賴于foo函數(shù),所以foo一直在內(nèi)存中,i變量也沒有被內(nèi)存回收機(jī)制回收。
那么如何實(shí)現(xiàn)彈出的是0,1,2呢?
利用之前提到的閉包就可以了,代碼如下:

    var result=[];
    function foo(){
        var i= 0;
        for (;i<3;i=i+1){
            (function () {
                var index=i;
                result[i]=function () {
                    alert(index);
                }
            })()
        }
    }
    foo();
    result[0](); // 0
    result[1](); // 1
    result[2](); // 2

利用立即執(zhí)行函數(shù)(IIF),我們可以創(chuàng)建一個閉包,在這個IIF內(nèi)部,我們使用index將i給保存下來了。具體執(zhí)行過程如下:

i=0;
(function () {
    var index=0;
    result[0]=function () {
        alert(index);
    }
})()
i=1;
(function () {
    var index=1;
    result[1]=function () {
        alert(index);
    }
})()
i=2;
(function () {
    var index=2;
    result[2]=function () {
        alert(index);
    }
})()

因?yàn)檫@些語句都放在IIF中,所以都有各自的作用域,index并不會重復(fù)。就像下方的代碼:

var sayHi=function(){
    var words="hi"
}
var sayHello=function(){
    var words="hello"
}

兩個方法中雖然都有words這個變量,但是因?yàn)樵诓煌暮瘮?shù)中,都有各自的作用域,所以互不干擾。

參考文獻(xiàn)

阮一峰:學(xué)習(xí)Javascript閉包(Closure)

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

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

  • 閉包(closure)是Javascript語言的一個難點(diǎn),也是它的特色,很多高級應(yīng)用都要依靠閉包實(shí)現(xiàn)。 一、變量...
    zock閱讀 1,117評論 2 6
  • 閉包(closure)是Javascript語言的一個難點(diǎn),也是它的特色,很多高級應(yīng)用都要依靠閉包實(shí)現(xiàn)。 一、變量...
    zouCode閱讀 1,357評論 0 13
  • ● 閉包基礎(chǔ) ● 閉包作用 ● 閉包經(jīng)典例子 ● 閉包應(yīng)用 ● 閉包缺點(diǎn) ● 參考資料 1、閉包基礎(chǔ) 作用域和作...
    lzyuan閱讀 1,032評論 0 0
  • 沒什么別的原因因?yàn)楦缭谝粋€新的文件夾下命名了一個相同的文件名就會報(bào)錯 "duplicate"和"symbols"。...
    小苗曉雪閱讀 232評論 0 0
  • 有時, 幸福很簡單; 騎一輛摩拜單車, 走一條清凈的大道, 聽一首思緒萬千的歌曲, 游走在, 既熟悉又陌生的城市,...
    金石已開閱讀 231評論 0 3

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