閉包

我們先來(lái)看一個(gè)簡(jiǎn)單的閉包函數(shù):

function  a(){                       //外層函數(shù)
    var n = 0;                         //私有變量
        function b(m){           //內(nèi)部函數(shù),私有函數(shù)
            n = n + m;               //遞加上級(jí)私有變量的值
            return n;              
        }
  return b;
}
var c = a();//調(diào)用外層函數(shù),返回內(nèi)部函數(shù)
c();
document.write(b(3));//輸出3
document.write(b(3));//輸出6,3+3
document.write(b(3));//輸出9,6+3
document.write(b(3));//輸出12,9+3

假如不使用如上的閉包函數(shù),當(dāng)調(diào)用外部函數(shù)a之后,其定義的私有變量就不存在,也就無(wú)法實(shí)現(xiàn)值的遞增效果。
所以,我們?nèi)绾螌?duì)外部函數(shù)b的私有變量n的值進(jìn)行長(zhǎng)時(shí)間的保存呢?
使用如上代碼所示的閉包。
如上代碼的步驟是:
(1)定義普通函數(shù) a
(2)在 a 中定義普通函數(shù) b
(3)在 a 中返回 b
(4)執(zhí)行 a, 并把 A 的返回結(jié)果賦值給變量 b
(5)執(zhí)行 c
函數(shù)a的內(nèi)部函數(shù)b被函數(shù)a外的一個(gè)變量 c 引用。即:

當(dāng)一個(gè)內(nèi)部函數(shù)被其外部函數(shù)之外的變量引用時(shí),就形成了一個(gè)閉包。

在了解閉包的作用之前,我們先了解一下 Javascript 中的GC機(jī)制:

在 Javascript 中,如果一個(gè)對(duì)象不再被引用,那么這個(gè)對(duì)象就會(huì)被 GC 回收,否則這個(gè)對(duì)象一直會(huì)保存在內(nèi)存中。

在上述例子中,b 定義在 a 中,因此 b 依賴(lài)于a,而外部變量 c 又引用了b, 所以a間接的被c 引用。
也就是說(shuō),A 不會(huì)被 GC 回收,會(huì)一直保存在內(nèi)存中。上述代碼3,6,9的值一直保存在內(nèi)存中,所以可以實(shí)現(xiàn)疊加。

閉包的高級(jí)寫(xiě)法

(function(document){
    var viewport;
    var obj = {
        init:function(id){
           viewport = document.querySelector("#"+id);
        },
        addChild:function(child){
            viewport.appendChild(child);
        },
        removeChild:function(child){
            viewport.removeChild(child);
        }
    }
    window.jView = obj;
})(document);

這個(gè)組件的作用是:初始化一個(gè)容器,然后可以給這個(gè)容器添加子容器,也可以移除一個(gè)容器。

功能很簡(jiǎn)單,但這里涉及到了另外一個(gè)概念:立即執(zhí)行函數(shù)。 簡(jiǎn)單了解一下就行,需要重點(diǎn)理解的是這種寫(xiě)法是如何實(shí)現(xiàn)閉包功能的。

可以將上面的代碼拆分成兩部分:(function(){}) 和 () , 第1個(gè)() 是一個(gè)表達(dá)式,而這個(gè)表達(dá)式本身是一個(gè)匿名函數(shù),所以在這個(gè)表達(dá)式后面加 () 就表示執(zhí)行這個(gè)匿名函數(shù)。

因此這段代碼執(zhí)行執(zhí)行過(guò)程可以分解如下:

var f = function(document){
    var viewport;
    var obj = {
        init:function(id){
            viewport = document.querySelector("#"+id);
        },
        addChild:function(child){
            viewport.appendChild(child);
        },
        removeChild:function(child){
            viewport.removeChild(child);
        }
    }
    window.jView = obj;
};
f(document);

在這段代碼中似乎看到了閉包的影子,但 f 中沒(méi)有任何返回值,似乎不具備閉包的條件,注意這句代碼:

window.jView = obj;

obj 是在函數(shù) f 中定義的一個(gè)對(duì)象,這個(gè)對(duì)象中定義了一系列方法, 執(zhí)行window.jView = obj 就是在 window 全局對(duì)象定義了一個(gè)變量 jView,并將這個(gè)變量指向 obj 對(duì)象,即全局變量 jView 引用了 obj . 而 obj 對(duì)象中的函數(shù)又引用了函數(shù) f 中的變量 viewport ,因此函數(shù) f 中的 viewport 不會(huì)被 GC 回收,viewport 會(huì)一直保存到內(nèi)存中,所以這種寫(xiě)法滿(mǎn)足了閉包的條件。

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 閉包(closure)是Javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。 一、變量...
    zock閱讀 1,118評(píng)論 2 6
  • 閉包(closure)是Javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。 一、變量...
    zouCode閱讀 1,360評(píng)論 0 13
  • 閉包: 官方”的解釋是:閉包是一個(gè)擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個(gè)函數(shù)),因而這些變量也是該...
    小裁縫sun閱讀 710評(píng)論 0 5
  • 上午看群信息無(wú)意中看到王老師推薦的兩本書(shū),剛好都是我家有的,于是話(huà)題打開(kāi)了,聊了幾句,王老師是做農(nóng)園的,從前...
    富足的驚喜麻麻閱讀 455評(píng)論 0 2
  • 1、做一下自我介紹: 2、然后就是提問(wèn)環(huán)節(jié); 說(shuō)一下YYModel的原理; 說(shuō)一下Masonry的原理; HTTP...
    韓叨叨閱讀 143評(píng)論 2 1

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