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

資訊專欄INFORMATION COLUMN

簡單而清楚地理解閉包

SimonMa / 2931人閱讀

摘要:大多數非閉包的情況下,函數的外部函數即全局變量函數被調用時,也會創建一條作用域鏈下稱鏈,并將鏈的內容包含到鏈中,然后將當前函數的活動對象可以簡單理解為所有的內部變量添加到鏈條的頂端。

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

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

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

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

閉包是如何產生的?
為了更清楚的解釋閉包的發生,我們需要先明白“函數的創建”到“函數的調用”到底發生了什么事情。

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

下面是一道經典的閉包題:

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

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


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


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

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

我們可以簡單理解為:函數創建時,就已經根據上下文環境保存一套所有外部函數(不包含自身內部)的變量。當我們在調用閉包函數時,閉包函數自身不存在的變量,將會在這套變量中查找。

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101038.html

相關文章

  • js閉包的底層實現和開發技巧

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

    Caizhenhao 評論0 收藏0
  • 前端基礎

    摘要:談起閉包,它可是兩個核心技術之一異步基于打造前端持續集成開發環境本文將以一個標準的項目為例,完全拋棄傳統的前端項目開發部署方式,基于容器技術打造一個精簡的前端持續集成的開發環境。 這一次,徹底弄懂 JavaScript 執行機制 本文的目的就是要保證你徹底弄懂javascript的執行機制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥,不論是面試求職,還是日...

    graf 評論0 收藏0
  • 理解 JavaScript this

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

    zombieda 評論0 收藏0
  • JavaScript閉包,只學這篇就夠了

    摘要:當在中調用匿名函數時,它們用的都是同一個閉包,而且在這個閉包中使用了和的當前值的值為因為循環已經結束,的值為。最好將閉包當作是一個函數的入口創建的,而局部變量是被添加進這個閉包的。 閉包不是魔法 這篇文章使用一些簡單的代碼例子來解釋JavaScript閉包的概念,即使新手也可以輕松參透閉包的含義。 其實只要理解了核心概念,閉包并不是那么的難于理解。但是,網上充斥了太多學術性的文章,對于...

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

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

    趙春朋 評論0 收藏0

發表評論

0條評論

SimonMa

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<