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

資訊專欄INFORMATION COLUMN

閉包里的微觀世界

Miyang / 2258人閱讀

摘要:本文旨在解釋閉包里的微觀世界。創(chuàng)建完活動對象后,把活動對象添加到的作用域的最頂端,此時的作用域鏈包含個對象的活動對象和對象。

本文旨在解釋閉包里的微觀世界

內(nèi)容包含:值類型作用域閉包

  

JS當(dāng)中所有的function都是閉包,一般說來,嵌套的function的閉包性更強。這也是我們平時接觸和研究比較多的地方。

在進入本文的核心部分以前,首先來理解幾個概念:

值類型

聲明一個值類型變量,編譯器會在棧上分配一個空間,這個空間對應(yīng)著該值的類型變量,空間存儲的就是這個變量的值。存儲在棧(stack)中的簡單數(shù)據(jù)段,也就是說,它們的值直接存儲在變量訪問的位置。

引用類型

引用類型的實例分配在堆(heap)上,新建一個引用類型的實例,得到的變量值對應(yīng)的是該實例的內(nèi)存分配地址。存儲在堆(heap)中的對象,也就是說,存儲在變量中的值是一個指針(point),其指向存儲對象的位置。

javascript//值類型
var a="xl";
var b=a;
a="XL";
console.log(b); //輸出  "xl"

//引用類型
var a={name:"xl"};
var b=a;
a.name="XL";
console.log(b.name);//輸出 "XL"

區(qū)別就是值類型變量是可以直接訪問棧(stack)中的值:

在第一段代碼中,將變量"a"賦值給"b",相當(dāng)于在stack中也為"b"開辟了一個存儲其值的空間,與存儲變量"a"的存儲空間是相互獨立的,因此修改"a"的值,不會影響到“b”的值。

在第二段代碼中,"a","b"都獲得的是對于存儲在heap當(dāng)中實例的引用,當(dāng)“a”對其進行修改的時候,“b”的引用也會受到影響。

接下來的內(nèi)容就是關(guān)于閉包的微觀世界

javascript    function a(){
        var i=0;
        function b(){
            console.log(++i);
        }
        return b;
    }

    var c=a(); //函數(shù)a執(zhí)行后返回函數(shù)b,并將函數(shù)b賦給c
    c();//輸出 1

本來這個地方變量i是定義在函數(shù)a中,并不能被函數(shù)a的外部所訪問,但是這個地方因為在a中定義了一個函數(shù)b,函數(shù)b中有對變量i的引用,因此當(dāng)b被a返回后,變量c獲得了對函數(shù)a中函數(shù)b的引用,因此i不會被GC回收,而是存在內(nèi)存當(dāng)中。

當(dāng)在一個函數(shù)a里面定義另外一個函數(shù)b,函數(shù)b有對函數(shù)a中變量的引用,當(dāng)函數(shù)a執(zhí)行并返回函數(shù)b,將b賦給變量c時,這樣就存在相互之間的引用關(guān)系,并形成了大家經(jīng)常見到的閉包

我們進一步的分析:這一部分的內(nèi)容包含了作用域作用域鏈部分的內(nèi)容.

依然拿上面的例子來分析:

當(dāng)定義函數(shù)a的時候,js解釋器會將函數(shù)a的作用域鏈(scope chain)設(shè)置為定義a時所在的“環(huán)境”,如果a是一個全局函數(shù),那么scope chain中只有window對象。

當(dāng)執(zhí)行函數(shù)a的時候,a會進入相應(yīng)的執(zhí)行環(huán)境(excution context).

在創(chuàng)建執(zhí)行環(huán)境的過程中,首先會為a添加scope屬性,即a的作用域,其值就為第一步的scope chain.即a.scope=a的作用域鏈。

然后執(zhí)行環(huán)境會創(chuàng)建一個活動對象(call object).活動對象也是一個擁有屬性的對象。但它不具有原型而且不能直接通過javascript代碼訪問。創(chuàng)建完活動對象后,把活動對象添加到a的作用域的最頂端,此時a的作用域鏈包含2個對象:a的活動對象和window對象。

下一步是在活動對象上添加一個arguments屬性,它保存著調(diào)用a時所傳遞的參數(shù)。最后把所有函數(shù)a的形參以及定義的內(nèi)部函數(shù)b添加到a的活動對象上。在這一步中,完成了函數(shù)b的定義,正如第一步,函數(shù)b的作用域鏈被設(shè)置為b被定義時所處的環(huán)境,即a的作用域
到此,整個函數(shù)a從定義到執(zhí)行的過程就完成了。此時a返回函數(shù)b的引用給c,又函數(shù)b的作用域鏈包含了對函數(shù)a的活動對象的引用,也就是說b可以訪問到a中定義的所有變量和函數(shù)。函數(shù)b被c引用,函數(shù)b又依賴函數(shù)的a,因此函數(shù)a在返回的時候不會被gc收回。

當(dāng)函數(shù)b執(zhí)行的時候,同樣會按上述步驟一樣。執(zhí)行時b的作用域里包含了3個對象:{b的活動對象}、{a的活動對象}、{window對象}

下面用2張圖來表示整個過程:

圖一展示了函數(shù)a定義過程是如何創(chuàng)建作用域鏈的

圖二展示了函數(shù)a執(zhí)行過程產(chǎn)生的活動對象(call object)

在這其中有個非常重要的內(nèi)容就是函數(shù)的作用域是在定義函數(shù)的時候就已經(jīng)確定,而不是在執(zhí)行的時候確定。

具體內(nèi)容參見:鳥哥:Javascript作用域和作用域鏈

再來看看我們在平時經(jīng)常遇到的一段代碼:

javascript    HTML部分:
        
1 2 3
JS: var spanArr=document.getElementById("example").getElementsByTagName("span"); for(var i=0;i<3;i++){ spanArr[i].onclick=function(){ console.log(i); } } //不管點擊哪個都會輸出3 //這是因為在內(nèi)部的匿名函數(shù)中i是對于外部的i的引用。當(dāng)for循環(huán)結(jié)束以后,i的值變?yōu)榱?.那么匿名函數(shù)相應(yīng)獲得的引用值夜都變?yōu)榱?.所以最后不管點擊哪個最后都會輸出3. //所以遇到這種情況的時候一般處理方法是 1.將變量i保存在每個span對象上。 for(var i=0;i<3;i++){ spanArr[i].i=i; spanArr[i].onclick=function(){ console.log(i); } } 2.加一層閉包 for(var i=0;i<3;i++){ (function(i){ spanArr[i].onclick=function(){ console.log(i); } })(i) } //當(dāng)然還有其他的方法,這里不多述。

參考文章:

理解javascript的作用域和作用域鏈

javascript閉包深入理解

理解javascript閉包

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

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

相關(guān)文章

  • 理解JavaScript的核心知識點:作用域

    摘要:也毫不例外,但在中作用域的特性與其他高級語言稍有不同,這是很多學(xué)習(xí)者久久難以理清的一個核心知識點。主要使用的是函數(shù)作用域。 關(guān)于作用域:About Scope 作用域是程序設(shè)計里的基礎(chǔ)特性,是作用域使得程序運行時可以使用變量存儲值、記錄和改變程序的狀態(tài)。JavaScript 也毫不例外,但在 JavaScript 中作用域的特性與其他高級語言稍有不同,這是很多學(xué)習(xí)者久久難以理清的一個核...

    HelKyle 評論0 收藏0
  • 理解javascript核心知識點

    摘要:作用域鏈的作用就是做標示符解析。事件循環(huán)還有個明顯的特點單線程。早期都是用作開發(fā),單線程可以比較好當(dāng)規(guī)避同步問題,降低了開發(fā)門檻。單線程需要解決的是效率問題,里的解決思想是異步非阻塞。 0、前言 本人在大學(xué)時非常癡迷java,認為java就是世界上最好的語言,偶爾在項目中會用到一些javascript,但基本沒放在眼里。較全面的接觸javascript是在實習(xí)的時候,通過這次的了解發(fā)現(xiàn)...

    laznrbfe 評論0 收藏0
  • 【進階3-5期】深度解析 new 原理及模擬實現(xiàn)

    摘要:使用指定的參數(shù)調(diào)用構(gòu)造函數(shù),并將綁定到新創(chuàng)建的對象。由構(gòu)造函數(shù)返回的對象就是表達式的結(jié)果。情況返回以外的基本類型實例中只能訪問到構(gòu)造函數(shù)中的屬性,和情況完全相反,結(jié)果相當(dāng)于沒有返回值。 定義 new 運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象的實例。 ——(來自于MDN) 舉個栗子 function Car(color) { this.color = co...

    Baaaan 評論0 收藏0
  • 【譯】閉包并不神秘

    摘要:下面我們就初步嘗試一下閉包現(xiàn)在來看一下發(fā)生了什么。于是,這種結(jié)構(gòu)就被稱作閉包。這就是閉包強大的地方。例如,如果我們可以在我們的計數(shù)器里面加一個名字我們可以往閉包里傳一個參數(shù)可以看出來,在實現(xiàn)過程中不僅能記住局部變量,也記住了傳進來的變量。 計數(shù)器 首先,從一個計數(shù)器開始。 var counter = 0; function increment() { counter = cou...

    sevi_stuo 評論0 收藏0
  • 談?wù)勎宜斫獾?em>閉包,js、php、golang里的closure

    摘要:當(dāng)初看這個解釋有點懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學(xué)習(xí)語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開始接觸編程是從js開始的,當(dāng)時網(wǎng)上很多人說閉包是難點,各種地方對閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發(fā)現(xiàn)不光是js,php、...

    betacat 評論0 收藏0

發(fā)表評論

0條評論

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