亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

js深入(三)作用域鏈與閉包

blair / 2499人閱讀

摘要:在之前我們根絕對(duì)象的原型說(shuō)過(guò)了的原型鏈,那么同樣的萬(wàn)物皆對(duì)象,函數(shù)也同樣存在這么一個(gè)鏈?zhǔn)降年P(guān)系,就是函數(shù)的作用域鏈作用域鏈?zhǔn)紫认葋?lái)回顧一下之前講到的原型鏈的尋找機(jī)制,就是實(shí)例會(huì)先從本身開(kāi)始找,沒(méi)有的話會(huì)一級(jí)一級(jí)的網(wǎng)上翻,直到頂端沒(méi)有就會(huì)報(bào)一

在之前我們根絕對(duì)象的原型說(shuō)過(guò)了js的原型鏈,那么同樣的js 萬(wàn)物皆對(duì)象,函數(shù)也同樣存在這么一個(gè)鏈?zhǔn)降年P(guān)系,就是函數(shù)的作用域鏈

作用域鏈

首先先來(lái)回顧一下之前講到的原型鏈的尋找機(jī)制,就是實(shí)例會(huì)先從本身開(kāi)始找,沒(méi)有的話會(huì)一級(jí)一級(jí)的網(wǎng)上翻,直到頂端沒(méi)有就會(huì)報(bào)一個(gè)undefined

同樣的js的機(jī)制就是這樣的,函數(shù)在執(zhí)行的時(shí)候會(huì)先函數(shù)本身的上下文的變量對(duì)象中查找,沒(méi)有的話,也會(huì)從這個(gè)函數(shù)被創(chuàng)建的時(shí)候的父級(jí)的執(zhí)行上下文的變量對(duì)象中去找(詞法環(huán)境),一直找到全局上下文的變量對(duì)象(比如客戶端的window對(duì)象),這個(gè)多層的執(zhí)行上下文的鏈?zhǔn)疥P(guān)系就是函數(shù)的作用域鏈

盜一張圖

作用域被創(chuàng)建的時(shí)機(jī)

大家可以看到,我在控制臺(tái)聲明了一個(gè)函數(shù),并且打印了他,這個(gè)a函數(shù)的里邊有一個(gè)[[scope]]屬性,
這是一個(gè)內(nèi)部屬性,當(dāng)一個(gè)函數(shù)被創(chuàng)建的時(shí)候,會(huì)保存所有的父級(jí)的變量對(duì)象(詞法環(huán)境)到這個(gè)里邊,比如說(shuō)上圖中 就有一個(gè)global 屬性展開(kāi)后,往下找你會(huì)發(fā)現(xiàn)很多我們常見(jiàn)的屬性和方法,比如alert等等

如圖

函數(shù)作用域的生命周期

姑且叫他生命周期,我是這么理解的,當(dāng)進(jìn)入一個(gè)函數(shù)的上下文,經(jīng)歷了創(chuàng)建階段之后,就會(huì)把函數(shù)的作用域鏈創(chuàng)建出來(lái),直到銷毀這個(gè)上下文,這個(gè)作用域鏈也是存在的

先來(lái)一個(gè)正經(jīng)的例子

function a(){
    var aaa = "aaa";
    return aaa;
}
checkscope();

這個(gè)函數(shù)的生命周期是這樣的

首先函數(shù)被創(chuàng)建,先把函數(shù)的作用域鏈保存到函數(shù)的[[scope]]屬性上邊

a.[[scope]] = [
    globalContext.VO//這個(gè)也就是我們上邊圖片里邊看的golbal
];
globalContext  全局上下文  VO 這個(gè)之前沒(méi)有介紹 是Variable object的簡(jiǎn)稱,也就是之前經(jīng)常提到的變量對(duì)象
還有一個(gè)AO ,這個(gè)AO指的是函數(shù)被激活的時(shí)候(被執(zhí)行)得活動(dòng)對(duì)象

創(chuàng)建完成之后,執(zhí)行到a函數(shù),創(chuàng)建了a函數(shù)得執(zhí)行上下文,并壓入執(zhí)行棧里邊

現(xiàn)在執(zhí)行棧里邊已經(jīng)有了兩個(gè)執(zhí)行上下文一個(gè)globalContext還有一個(gè)aContext

到了a函數(shù)之后,首先會(huì)做一些列得準(zhǔn)備工作,就是之前講到得函數(shù)得arguments,this等等

首先第一步復(fù)制之前得[[scope]]屬性,創(chuàng)建作用域鏈

aContext = {
    Scope: a.[[scope]],
}

然后開(kāi)始初始化活動(dòng)變量 argments對(duì)象 形參,函數(shù)聲明,變量聲明等等

最后把把活動(dòng)變量也塞到作用域鏈中去

以上,一個(gè)函數(shù)得準(zhǔn)備工作就算是做完了,然后下一步就是函數(shù)得執(zhí)行階段

之前講過(guò),在之后階段得時(shí)候函數(shù)會(huì)根據(jù)代碼給之前得活動(dòng)對(duì)象賦值,然后執(zhí)行里邊得代碼,直到執(zhí)行完畢

最后,函數(shù)執(zhí)行完畢,函數(shù)得上下文被從上下文棧中彈出銷毀

在彈出得最后時(shí)候,a函數(shù)得結(jié)構(gòu)大概長(zhǎng)成這個(gè)樣子

aContext = {
    AO: {
        arguments: {
            length: 0
        },
    },
    Scope: [AO, [[Scope]]]
}

接下來(lái)我們?cè)谂e一個(gè)不正經(jīng)得例子,就是為了證明一下作用域鏈即使在函數(shù)被銷毀后,也會(huì)存在這么一個(gè)事實(shí)

閉包

首先什么是閉包,閉包是指在一個(gè)函數(shù)內(nèi)部能夠訪問(wèn)不是函數(shù)得參數(shù),也不是局部變量得函數(shù),所以廣義得講我們用的所有得函數(shù)都是可算作是閉包,都能訪問(wèn)全局變量。。。

不過(guò)工作中不是這樣子得,說(shuō)正題,給上邊得問(wèn)題舉個(gè)例子

var item = "1"
function a(){
    var item = "2"
    function b(){
        return item
    }
    return b;
}

var foo = a();
foo();

試著猜想一下這段代碼得執(zhí)行過(guò)程

還是來(lái)一步一步得解釋一下

首先不用多想,進(jìn)入全局代碼,創(chuàng)建全局執(zhí)行上下文,推入執(zhí)行棧,全局上下文得一系列初始化

然后創(chuàng)建a , 創(chuàng)建上下文,推入執(zhí)行棧,一些列得初始化

在執(zhí)行a得時(shí)候創(chuàng)建了b函數(shù),這個(gè)時(shí)候,還記得上邊之前說(shuō)過(guò)得把,作用域鏈?zhǔn)窃诒粍?chuàng)建得時(shí)候確定得

這個(gè)時(shí)候得b函數(shù)得作用域鏈應(yīng)該是這個(gè)樣子的

bContext = {
    Scope: [AO, aContext.AO, globalContext.VO],
}

這個(gè)是重點(diǎn),我們先把執(zhí)行過(guò)程說(shuō)完

在a函數(shù)執(zhí)行完畢之后,a的上下文棧被彈出

然后在后邊執(zhí)行b函數(shù),然后一樣的套路,進(jìn)上下文壓入棧

進(jìn)棧一些列的初始化

執(zhí)行完畢b的上下文被彈出

上邊已經(jīng)把順序說(shuō)的很清楚了對(duì)吧, 執(zhí)行過(guò)程是a進(jìn)棧出棧,b進(jìn)棧出棧,但是你打印這段代碼的時(shí)候
會(huì)打印出一個(gè)2,就是因?yàn)殡m然說(shuō)a的上下文被銷毀了,但是b的作用域鏈里邊還是有a的活動(dòng)對(duì)象的
,在b的上下文里邊可以找到這個(gè)item

這也就是我們之前所說(shuō)的閉包,也符合閉包的定義

創(chuàng)建他的函數(shù)的上下文被銷毀,但是他依然存在

在代碼中引用了不是自身的參數(shù)或者局部變量

最后放一個(gè)網(wǎng)上很常見(jiàn)的面試題

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0]();
data[1]();
data[2]();

從作用域鏈的角度思考一下會(huì)打印出什么結(jié)果,為什么會(huì)打印出這個(gè)結(jié)果

以上是我對(duì)js的作用域鏈和閉包的一些認(rèn)識(shí),有不足之處,希望批評(píng)指正

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/105504.html

相關(guān)文章

  • 前端基礎(chǔ)進(jìn)階(六):在chrome開(kāi)發(fā)者工具中觀察函數(shù)調(diào)用棧、作用鏈與閉包

    摘要:在的開(kāi)發(fā)者工具中,通過(guò)斷點(diǎn)調(diào)試,我們能夠非常方便的一步一步的觀察的執(zhí)行過(guò)程,直觀感知函數(shù)調(diào)用棧,作用域鏈,變量對(duì)象,閉包,等關(guān)鍵信息的變化。其中表示當(dāng)前的局部變量對(duì)象,表示當(dāng)前作用域鏈中的閉包。 showImg(https://segmentfault.com/img/remote/1460000008404321); 在前端開(kāi)發(fā)中,有一個(gè)非常重要的技能,叫做斷點(diǎn)調(diào)試。 在chrome...

    draveness 評(píng)論0 收藏0
  • “動(dòng)靜結(jié)合” 小白初探靜態(tài)(詞法)作用域,作用鏈與執(zhí)行環(huán)境(EC)

    摘要:圖片中的作用域鏈,是全局執(zhí)行環(huán)境中的作用域鏈。然后此活動(dòng)對(duì)象被推入作用域鏈的最前端。在最后調(diào)用的時(shí)候,創(chuàng)建先構(gòu)建作用域鏈,再創(chuàng)建執(zhí)行環(huán)境,再創(chuàng)建執(zhí)行環(huán)境的時(shí)候發(fā)現(xiàn)了一個(gè)變量標(biāo)識(shí)符。 從圖書(shū)館翻過(guò)各種JS的書(shū)之后,對(duì)作用域/執(zhí)行環(huán)境/閉包這些概念有了一個(gè)比較清晰的認(rèn)識(shí)。 栗子說(shuō)明一切 第一個(gè)栗子 來(lái)看一個(gè)來(lái)自ECMA-262的栗子: var x = 10; (function foo(...

    Drummor 評(píng)論0 收藏0
  • 前端基礎(chǔ)進(jìn)階(四):詳細(xì)圖解作用鏈與閉包

    摘要:之前一篇文章我們?cè)敿?xì)說(shuō)明了變量對(duì)象,而這里,我們將詳細(xì)說(shuō)明作用域鏈。而的作用域鏈,則同時(shí)包含了這三個(gè)變量對(duì)象,所以的執(zhí)行上下文可如下表示。下圖展示了閉包的作用域鏈。其中為當(dāng)前的函數(shù)調(diào)用棧,為當(dāng)前正在被執(zhí)行的函數(shù)的作用域鏈,為當(dāng)前的局部變量。 showImg(https://segmentfault.com/img/remote/1460000008329355);初學(xué)JavaScrip...

    aikin 評(píng)論0 收藏0
  • JS基礎(chǔ)-作用域、作用鏈與閉包 Part three

    摘要:作用域執(zhí)行上下文變量提前函數(shù)聲明提前確定值范圍一段或者一個(gè)函數(shù)都會(huì)生成一個(gè)執(zhí)行上下文全局一段變量定義函數(shù)聲明函數(shù)變量定義函數(shù)聲明參數(shù)集合變量提前代碼解析執(zhí)行過(guò)程變量定義提前賦值函數(shù)聲明提前代碼解析函數(shù)聲明函數(shù)表達(dá)式執(zhí)行過(guò)程執(zhí)行過(guò)程執(zhí)行時(shí)才能 1.作用域 執(zhí)行上下文 (變量提前、函數(shù)聲明提前、確定this值、arguments) 范圍:一段或者一個(gè)函數(shù)(都會(huì)生成一個(gè)執(zhí)行上下文) ...

    heartFollower 評(píng)論0 收藏0
  • Javascript 函數(shù)、作用鏈與閉包

    摘要:而外層的函數(shù)不能訪問(wèn)內(nèi)層的變量或函數(shù),這樣的層層嵌套就形成了作用域鏈。閉包閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的最常見(jiàn)的方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建另一個(gè)函數(shù),通過(guò)另一個(gè)函數(shù)訪問(wèn)這個(gè)函數(shù)的局部變量。 閉包是js中一個(gè)極為NB的武器,但也不折不扣的成了初學(xué)者的難點(diǎn)。因?yàn)閷W(xué)好閉包就要學(xué)好作用域,正確理解作用域鏈,然而想做到這一點(diǎn)就要深入的理解函數(shù),所以我們從函數(shù)說(shuō)起。 函數(shù)...

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

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

0條評(píng)論

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