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

資訊專(zhuān)欄INFORMATION COLUMN

閉包里的微觀世界

Miyang / 2264人閱讀

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

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

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

  

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

在進(jìn)入本文的核心部分以前,首先來(lái)理解幾個(gè)概念:

值類(lèi)型

聲明一個(gè)值類(lèi)型變量,編譯器會(huì)在棧上分配一個(gè)空間,這個(gè)空間對(duì)應(yīng)著該值的類(lèi)型變量,空間存儲(chǔ)的就是這個(gè)變量的值。存儲(chǔ)在棧(stack)中的簡(jiǎn)單數(shù)據(jù)段,也就是說(shuō),它們的值直接存儲(chǔ)在變量訪(fǎng)問(wèn)的位置。

引用類(lèi)型

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

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

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

區(qū)別就是值類(lèi)型變量是可以直接訪(fǎng)問(wèn)棧(stack)中的值:

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

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

接下來(lái)的內(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

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

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

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

依然拿上面的例子來(lái)分析:

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

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

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

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

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

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

下面用2張圖來(lái)表示整個(gè)過(guò)程:

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

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

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

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

再來(lái)看看我們?cè)谄綍r(shí)經(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); } } //不管點(diǎn)擊哪個(gè)都會(huì)輸出3 //這是因?yàn)樵趦?nèi)部的匿名函數(shù)中i是對(duì)于外部的i的引用。當(dāng)for循環(huán)結(jié)束以后,i的值變?yōu)榱?.那么匿名函數(shù)相應(yīng)獲得的引用值夜都變?yōu)榱?.所以最后不管點(diǎn)擊哪個(gè)最后都會(huì)輸出3. //所以遇到這種情況的時(shí)候一般處理方法是 1.將變量i保存在每個(gè)span對(duì)象上。 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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

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

相關(guān)文章

  • 理解JavaScript的核心知識(shí)點(diǎn):作用域

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

    HelKyle 評(píng)論0 收藏0
  • 理解javascript核心知識(shí)點(diǎn)

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

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

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

    Baaaan 評(píng)論0 收藏0
  • 【譯】閉包并不神秘

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

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

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

    betacat 評(píng)論0 收藏0

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

0條評(píng)論

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