国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

簡(jiǎn)單而清楚地理解閉包

SimonMa / 2924人閱讀

摘要:大多數(shù)非閉包的情況下,函數(shù)的外部函數(shù)即全局變量函數(shù)被調(diào)用時(shí),也會(huì)創(chuàng)建一條作用域鏈下稱鏈,并將鏈的內(nèi)容包含到鏈中,然后將當(dāng)前函數(shù)的活動(dòng)對(duì)象可以簡(jiǎn)單理解為所有的內(nèi)部變量添加到鏈條的頂端。

什么是閉包?
“閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。”---《JavaScript高級(jí)程序設(shè)計(jì)》
通常來說,當(dāng)一個(gè)函數(shù)可以訪問另一個(gè)函數(shù)內(nèi)部定義的變量(包括屬性和方法)時(shí),這個(gè)函數(shù)可以稱之為閉包:

function fnA(){
    var a = "this is fnA.a";
    return function fnB(){
        alert(a);
    }
}

var x = fnA();
x(); // "this is fnA.a"

例子中,我們可以通過x(即fnB)去訪問fnA中的內(nèi)部變量(a),此時(shí)我們可以稱fnB為閉包。

閉包是如何產(chǎn)生的?
為了更清楚的解釋閉包的發(fā)生,我們需要先明白“函數(shù)的創(chuàng)建”到“函數(shù)的調(diào)用”到底發(fā)生了什么事情。

1、函數(shù)被創(chuàng)建時(shí),會(huì)創(chuàng)建一條作用域鏈(下稱A鏈)。然后根據(jù)跟創(chuàng)建時(shí)的環(huán)境,依照“外部函數(shù)”、“‘外部函數(shù)’的外部函數(shù)”、“‘外部函數(shù)的外部函數(shù)’的外部函數(shù)”....“全局函數(shù)”順序,將所有函數(shù)的活動(dòng)對(duì)象(可以簡(jiǎn)單理解為所有的內(nèi)部變量)添加到這條作用域鏈上。(大多數(shù)非閉包的情況下,函數(shù)的外部函數(shù)即全局變量)
2、函數(shù)被調(diào)用時(shí),也會(huì)創(chuàng)建一條作用域鏈(下稱B鏈),并將A鏈的內(nèi)容包含到B鏈中,然后將當(dāng)前函數(shù)的活動(dòng)對(duì)象(可以簡(jiǎn)單理解為所有的內(nèi)部變量)添加到B鏈條的頂端。
3、當(dāng)訪問函數(shù)內(nèi)部變量時(shí),會(huì)按照B鏈中的變量保存的順序依次訪問。即內(nèi)部變量,(創(chuàng)建時(shí)的)外部函數(shù)的變量,(創(chuàng)建時(shí)的)外部函數(shù)的外部函數(shù)的變量...全局變量。

下面是一道經(jīng)典的閉包題:

function fun(n,o) {
    console.log(o)
    return {
    fun:function(m){
        return fun(m,n);
        }
    };
}

var a = fun(0); // undefined。由于會(huì)“o”未賦值,所以會(huì)顯示:undefined。同時(shí)返回一個(gè)字面量對(duì)象,對(duì)象內(nèi)創(chuàng)建一個(gè)名為“fun”的函數(shù),并將對(duì)象返回賦值給全局變量a。此時(shí)a內(nèi)部的函數(shù)fun已經(jīng)被創(chuàng)建好了,它的作用域鏈上包含了外部函數(shù)(外層的fun函數(shù))的所有變量,其中包含了n(值為0),o(值為undefined);以及全局函數(shù)的變量fun(值得注意的是,這個(gè)fun屬于全局函數(shù)的變量)。
a.fun(1); // 0。上面提到。在創(chuàng)建a的內(nèi)部fun時(shí),它包含的作用域鏈中包含了n(值為0),o(值為undefined);以及全局函數(shù)的變量fun。因此,我們調(diào)用(訪問)的“fun”是作用域鏈中給全局函數(shù)的函數(shù)fun。m=1,n=0,將其賦值給全局函數(shù)的函數(shù)fun,即:n=(m=)1,o=(n=)0,打印0,值為“0”。
a.fun(2); // 0
a.fun(3); // 0。這里有個(gè)“坑”需要注意。在上個(gè)步驟“a.fun(1);”中,最后會(huì)創(chuàng)建一個(gè)對(duì)象(fun函數(shù)作用域鏈中的n值為1,o值為0)并返回。但是并沒有變量來接收這個(gè)對(duì)象,更不會(huì)影響到a內(nèi)部作用域鏈。因此“a.fun(2);”、“a.fun(3);”中,作用域鏈上的值與“a.fun(1);”中完全一樣。


var b = fun(0).fun(1).fun(2).fun(3); // undefined,0,1,2
//這是一條鏈?zhǔn)秸{(diào)用。為了便于理解,我們將鏈?zhǔn)秸{(diào)用拆分以下等價(jià)的方案:
var b1 = fun(0); // undefined。這個(gè)和“ var a = fun(0);”,不重復(fù)解釋。
var b2 = b1.fun(1); // 0。這里和“a.fun(1);”一樣,不重復(fù)解釋。但是要注意的是,此時(shí)有個(gè)變量b2接收了b1.fun返回的變量。此時(shí),b2中的函數(shù)fun的作用域鏈的(部分)內(nèi)容情況:n=1,o=0。
var b3 = b2.fun(2); // 1。“var b2 = b1.fun(1);”中,b2中函數(shù)fun的作用域鏈中的n為1,o為0。調(diào)用全局函數(shù)的fun時(shí),n=(m=)2,o=(n=)1。因此打印內(nèi)容為“1”。
var b4 = b3.fun(3); // 2。理由同上。


var c = fun(0).fun(1); // undefined,0
c.fun(2);// 1
c.fun(3);// 1

//為了便于理解,我們將鏈?zhǔn)秸{(diào)用拆分以下等價(jià)的方案進(jìn)行解釋:
var c1 = fun(0); // undefined。這個(gè)和“ var a = fun(0);”,不重復(fù)解釋。
var c = c1.fun(1); // 0。要注意的是,“ c1.fun(1); ”返回的對(duì)象由變量c接收,即c中的函數(shù)fun作用域鏈中的變量:n=1,o=0。
c.fun(2);// 1。
c.fun(3);// 1。“ c.fun(2);”中返回的對(duì)象不會(huì)影響到c。因此此處和執(zhí)行“c.fun(2);”時(shí)一樣,c中的函數(shù)fun作用域鏈并未被改變。

我們可以簡(jiǎn)單理解為:函數(shù)創(chuàng)建時(shí),就已經(jīng)根據(jù)上下文環(huán)境保存一套所有外部函數(shù)(不包含自身內(nèi)部)的變量。當(dāng)我們?cè)谡{(diào)用閉包函數(shù)時(shí),閉包函數(shù)自身不存在的變量,將會(huì)在這套變量中查找。

值得一提
1、“變量聲明提升”對(duì)于閉包的實(shí)現(xiàn)是非常重要的。如果變量聲明沒有被提升,那么我們將無法保存那些在閉包函數(shù)創(chuàng)建以后才聲明的變量。
2、閉包的機(jī)制,作用域鏈會(huì)一直引用自身以外的函數(shù)的全部變量,內(nèi)存回收機(jī)制不能及時(shí)回收這些變量,從而增大內(nèi)存開銷。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/101038.html

相關(guān)文章

  • js閉包的底層實(shí)現(xiàn)和開發(fā)技巧

    摘要:沒有清空的原因是,內(nèi)部函數(shù)返回的匿名函數(shù)的作用域鏈仍然保有對(duì)外部函數(shù)的變量的引用。在作用域鏈中,外部函數(shù)的活動(dòng)對(duì)象始終處于第二位,外部函數(shù)的外部函數(shù)的活動(dòng)對(duì)象處于第三位,直至作為作用域鏈終點(diǎn)的全局執(zhí)行環(huán)境。 前言 閉包這個(gè)概念幾乎成了JavaScript面試者必問的話題之一,可以毫不客氣地說對(duì)閉包的理解和運(yùn)用體現(xiàn)了一名js工程師的功底。那么閉包到底是什么,它又能帶來什么特別的作用?網(wǎng)上...

    Caizhenhao 評(píng)論0 收藏0
  • 前端基礎(chǔ)

    摘要:談起閉包,它可是兩個(gè)核心技術(shù)之一異步基于打造前端持續(xù)集成開發(fā)環(huán)境本文將以一個(gè)標(biāo)準(zhǔn)的項(xiàng)目為例,完全拋棄傳統(tǒng)的前端項(xiàng)目開發(fā)部署方式,基于容器技術(shù)打造一個(gè)精簡(jiǎn)的前端持續(xù)集成的開發(fā)環(huán)境。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥,不論是面試求職,還是日...

    graf 評(píng)論0 收藏0
  • 理解 JavaScript this

    摘要:回調(diào)函數(shù)在回調(diào)函數(shù)中的指向也會(huì)發(fā)生變化。在閉包回調(diào)函數(shù)賦值等場(chǎng)景下我們都可以利用來改變的指向,以達(dá)到我們的預(yù)期。文章參考系列文章理解閉包理解執(zhí)行棧理解作用域理解數(shù)據(jù)類型與變量原文發(fā)布在我的公眾號(hào),點(diǎn)擊查看。 這是本系列的第 5 篇文章。 還記得上一篇文章中的閉包嗎?點(diǎn)擊查看文章 理解 JavaScript 閉包 。 在聊 this 之前,先來復(fù)習(xí)一下閉包: var name = Nei...

    zombieda 評(píng)論0 收藏0
  • JavaScript閉包,只學(xué)這篇就夠了

    摘要:當(dāng)在中調(diào)用匿名函數(shù)時(shí),它們用的都是同一個(gè)閉包,而且在這個(gè)閉包中使用了和的當(dāng)前值的值為因?yàn)檠h(huán)已經(jīng)結(jié)束,的值為。最好將閉包當(dāng)作是一個(gè)函數(shù)的入口創(chuàng)建的,而局部變量是被添加進(jìn)這個(gè)閉包的。 閉包不是魔法 這篇文章使用一些簡(jiǎn)單的代碼例子來解釋JavaScript閉包的概念,即使新手也可以輕松參透閉包的含義。 其實(shí)只要理解了核心概念,閉包并不是那么的難于理解。但是,網(wǎng)上充斥了太多學(xué)術(shù)性的文章,對(duì)于...

    CoderBear 評(píng)論0 收藏0
  • 十分鐘快速了解《你不知道的 JavaScript》(上卷)

    摘要:最近剛剛看完了你不知道的上卷,對(duì)有了更進(jìn)一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對(duì)象原型。附錄詞法這一章并沒有說明機(jī)制,只是介紹了中的箭頭函數(shù)引入的行為詞法。第章混合對(duì)象類類理論類的機(jī)制類的繼承混入。 最近剛剛看完了《你不知道的 JavaScript》上卷,對(duì) JavaScript 有了更進(jìn)一步的了解。 《你不知道的 JavaScript》上卷由兩部...

    趙春朋 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<