成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

簡單而清楚地理解閉包

SimonMa / 2999人閱讀

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

什么是閉包?
“閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)?!?--《JavaScript高級程序設計》
通常來說,當一個函數(shù)可以訪問另一個函數(shù)內(nèi)部定義的變量(包括屬性和方法)時,這個函數(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),此時我們可以稱fnB為閉包。

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

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

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

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

var a = fun(0); // undefined。由于會“o”未賦值,所以會顯示:undefined。同時返回一個字面量對象,對象內(nèi)創(chuàng)建一個名為“fun”的函數(shù),并將對象返回賦值給全局變量a。此時a內(nèi)部的函數(shù)fun已經(jīng)被創(chuàng)建好了,它的作用域鏈上包含了外部函數(shù)(外層的fun函數(shù))的所有變量,其中包含了n(值為0),o(值為undefined);以及全局函數(shù)的變量fun(值得注意的是,這個fun屬于全局函數(shù)的變量)。
a.fun(1); // 0。上面提到。在創(chuàng)建a的內(nèi)部fun時,它包含的作用域鏈中包含了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。這里有個“坑”需要注意。在上個步驟“a.fun(1);”中,最后會創(chuàng)建一個對象(fun函數(shù)作用域鏈中的n值為1,o值為0)并返回。但是并沒有變量來接收這個對象,更不會影響到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
//這是一條鏈式調(diào)用。為了便于理解,我們將鏈式調(diào)用拆分以下等價的方案:
var b1 = fun(0); // undefined。這個和“ var a = fun(0);”,不重復解釋。
var b2 = b1.fun(1); // 0。這里和“a.fun(1);”一樣,不重復解釋。但是要注意的是,此時有個變量b2接收了b1.fun返回的變量。此時,b2中的函數(shù)fun的作用域鏈的(部分)內(nèi)容情況:n=1,o=0。
var b3 = b2.fun(2); // 1?!皏ar b2 = b1.fun(1);”中,b2中函數(shù)fun的作用域鏈中的n為1,o為0。調(diào)用全局函數(shù)的fun時,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

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

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

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

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

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

相關文章

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

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

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

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

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

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

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

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

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

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

    趙春朋 評論0 收藏0

發(fā)表評論

0條評論

SimonMa

|高級講師

TA的文章

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