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

資訊專(zhuān)欄INFORMATION COLUMN

徹底理解Javascript中的作用域鏈

zhunjiee / 659人閱讀

摘要:全局和上下文中的作用域鏈這里不一定很有趣,但必須要提示一下。全局上下文的作用域鏈僅包含全局對(duì)象。代碼的上下文與當(dāng)前的調(diào)用上下文擁有同樣的作用域鏈。代碼執(zhí)行時(shí)對(duì)作用域鏈的影響在中,在代碼執(zhí)行階段有兩個(gè)聲明能修改作用域鏈。

1 定義

我們已經(jīng)知道一個(gè)執(zhí)行上下文中的數(shù)據(jù)(參數(shù),變量,函數(shù))作為屬性存儲(chǔ)在變量對(duì)象中。

也知道變量對(duì)象是在每次進(jìn)入上下文是創(chuàng)建并填入初始值,值的更新出現(xiàn)在代碼執(zhí)行階段。

作用域鏈就是這些變量對(duì)象的鏈表。

讓我們看一下和作用域相關(guān)的上下文結(jié)構(gòu)
VO是當(dāng)前上下文的變量對(duì)象,重點(diǎn)是Scope屬性,Scope = VO+[[scope]]。其中[[scope]]為所有父上下文變量對(duì)象的鏈表。

activeExecutionContext = {
    VO: {...}, // or AO
    this: thisValue,
    Scope: [ // Scope chain
      // 所有變量對(duì)象的列表
      // for identifiers lookup
    ]
};

函數(shù)的生命周期分為創(chuàng)建和激活。

2 函數(shù)創(chuàng)建階段
var x = 10;
  
function foo() {
  var y = 20;
  alert(x + y);
}
  
foo(); // 30

此前,我們僅僅談到有關(guān)當(dāng)前上下文的變量對(duì)象。這里,我們看到變量“y”在函數(shù)“foo”中定義(意味著它在foo上下文的AO中),但是變量“x”并未在“foo”上下文中定義,相應(yīng)地,它也不會(huì)添加到“foo”的AO中。乍一看,變量“x”相對(duì)于函數(shù)“foo”根本就不存在;但正如我們?cè)谙旅婵吹降摹矁H僅是“一瞥”,我們發(fā)現(xiàn),“foo”上下文的活動(dòng)對(duì)象中僅包含一個(gè)屬性--“y”。

fooContext.AO = {
y: undefined // undefined – 進(jìn)入上下文的時(shí)候是20 – at activation
};

函數(shù)“foo”如何訪(fǎng)問(wèn)到變量“x”?理論上函數(shù)應(yīng)該能訪(fǎng)問(wèn)一個(gè)更高一層上下文的變量對(duì)象。實(shí)際上它正是這樣,這種機(jī)制是通過(guò)函數(shù)內(nèi)部的[[scope]]屬性來(lái)實(shí)現(xiàn)的。

[[scope]]是所有父變量對(duì)象的層級(jí)鏈,處于當(dāng)前函數(shù)上下文之上,在函數(shù)創(chuàng)建時(shí)存于其中。

注意這重要的一點(diǎn)--[[scope]]在函數(shù)創(chuàng)建時(shí)被存儲(chǔ)--靜態(tài)(不變的),永遠(yuǎn)永遠(yuǎn),直至函數(shù)銷(xiāo)毀。即:函數(shù)可以永不調(diào)用,但[[scope]]屬性已經(jīng)寫(xiě)入,并存儲(chǔ)在函數(shù)對(duì)象中。

3 函數(shù)激活階段

正如在定義中說(shuō)到的,進(jìn)入上下文創(chuàng)建AO/VO之后,上下文的Scope屬性(變量查找的一個(gè)作用域鏈)作如下定義:

Scope = AO|VO + [[Scope]]

上面代碼的意思是:活動(dòng)對(duì)象是作用域數(shù)組的第一個(gè)對(duì)象,即添加到作用域的前端。
Scope = [AO].concat([[Scope]]);

這個(gè)特點(diǎn)對(duì)于標(biāo)示符解析的處理來(lái)說(shuō)很重要。

標(biāo)示符解析是一個(gè)處理過(guò)程,用來(lái)確定一個(gè)變量(或函數(shù)聲明)屬于哪個(gè)變量對(duì)象。
標(biāo)識(shí)符解析過(guò)程包含與變量名對(duì)應(yīng)屬性的查找,即作用域中變量對(duì)象的連續(xù)查找,從最深的上下文開(kāi)始,繞過(guò)作用域鏈直到最上層。

這樣一來(lái),在向上查找中,一個(gè)上下文中的局部變量較之于父作用域的變量擁有較高的優(yōu)先級(jí)。萬(wàn)一兩個(gè)變量有相同的名稱(chēng)但來(lái)自不同的作用域,那么第一個(gè)被發(fā)現(xiàn)的是在最深作用域中。

4 閉包

在ECMAScript中,閉包與函數(shù)的[[scope]]直接相關(guān),正如我們提到的那樣,[[scope]]在函數(shù)創(chuàng)建時(shí)被存儲(chǔ),與函數(shù)共存亡。實(shí)際上,閉包是函數(shù)代碼和其[[scope]]的結(jié)合。

因?yàn)殚]包函數(shù)在創(chuàng)建的時(shí)候就創(chuàng)建了父級(jí)的變量對(duì)象鏈表,也就是父級(jí)作用域鏈, 然后閉包函數(shù)再訪(fǎng)問(wèn)父級(jí)作用域鏈中的變量,導(dǎo)致父級(jí)函數(shù)執(zhí)行完畢后仍然不能釋放執(zhí)行上下文的情況。

5 通過(guò)構(gòu)造函數(shù)創(chuàng)建的函數(shù)的[[scope]]

在上面的例子中,我們看到,在函數(shù)創(chuàng)建時(shí)獲得函數(shù)的[[scope]]屬性,通過(guò)該屬性訪(fǎng)問(wèn)到所有父上下文的變量。但是,這個(gè)規(guī)則有一個(gè)重要的例外,它涉及到通過(guò)函數(shù)構(gòu)造函數(shù)創(chuàng)建的函數(shù)。

var x = 10;
  
function foo() {
  
 var y = 20;
  
 function barFD() { // 函數(shù)聲明
alert(x);
alert(y);
}
  
 var barFE = function () { // 函數(shù)表達(dá)式
alert(x);
alert(y);
};
  
 var barFn = Function("alert(x); alert(y);");
  
barFD(); // 10, 20
barFE(); // 10, 20
barFn(); // 10, "y" is not defined
  
}
  
foo();

我們看到,通過(guò)函數(shù)構(gòu)造函數(shù)(Function constructor)創(chuàng)建的函數(shù)“bar”,是不能訪(fǎng)問(wèn)變量“y”的。但這并不意味著函數(shù)“barFn”沒(méi)有[[scope]]屬性(否則它不能訪(fǎng)問(wèn)到變量“x”)。問(wèn)題在于通過(guò)函構(gòu)造函數(shù)創(chuàng)建的函數(shù)的[[scope]]屬性總是唯一的全局對(duì)象??紤]到這一點(diǎn),如通過(guò)這種函數(shù)創(chuàng)建除全局之外的最上層的上下文閉包是不可能的。

6 全局和eval上下文中的作用域鏈

這里不一定很有趣,但必須要提示一下。全局上下文的作用域鏈僅包含全局對(duì)象。代碼eval的上下文與當(dāng)前的調(diào)用上下文(calling context)擁有同樣的作用域鏈。

globalContext.Scope = [
Global
];
  
evalContext.Scope === callingContext.Scope;
7 代碼執(zhí)行時(shí)對(duì)作用域鏈的影響

在ECMAScript 中,在代碼執(zhí)行階段有兩個(gè)聲明能修改作用域鏈。這就是with聲明和catch語(yǔ)句。它們添加到作用域鏈的最前端,對(duì)象須在這些聲明中出現(xiàn)的標(biāo)識(shí)符中查找。如果發(fā)生其中的一個(gè),作用域鏈簡(jiǎn)要的作如下修改:

Scope = withObject|catchObject + AO|VO + [[Scope]]

eval代碼運(yùn)行的字符串利用當(dāng)前調(diào)用的上下文,并且能夠修改當(dāng)前上下文中的變量對(duì)象,也就是說(shuō)eval內(nèi)和eval外的代碼一樣,只是不能變量提升,執(zhí)行起來(lái)是一樣的。
with代碼塊和catch代碼塊都改變了作用域鏈,但是在他們代碼塊中聲明的變量,也存在了函數(shù)作用域中,只是with的對(duì)象和catch對(duì)象外部不能訪(fǎng)問(wèn)而已。

eval("var x=3");
console.log(x); //3      
with (obj1) {
    var innner ="inner";
    console.log(a); //1
    console.log(b); //2
}
console.log(innner); // inner 仍能訪(fǎng)問(wèn)
console.log(a) //訪(fǎng)問(wèn)不到
try {
    throw new Error("error")
}
catch (e) {
    var cat = 2;
}
console.log(cat); //2 仍能訪(fǎng)問(wèn)

英文原文:http://dmitrysoshnikov.com/ec...
本文絕大部分內(nèi)容來(lái)自上述地址,僅做少許修改

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

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

相關(guān)文章

  • 徹底明白作用域、執(zhí)行上下文

    摘要:代碼執(zhí)行階段在這個(gè)階段會(huì)生成三個(gè)重要的東西變量對(duì)象,作用域鏈變量對(duì)象在函數(shù)上下文中,我們用活動(dòng)對(duì)象來(lái)表示變量對(duì)象。這時(shí)候執(zhí)行上下文的作用域鏈,我們命名為至此,作用域鏈創(chuàng)建完畢。 好久沒(méi)更新文章了,這一憋就是一個(gè)大的。說(shuō)起js中的概念,執(zhí)行上下文和作用域應(yīng)該是大家最容易混淆的,你說(shuō)混淆就混淆吧,其實(shí)大多數(shù)人在開(kāi)發(fā)的時(shí)候不是很關(guān)注這兩個(gè)名詞,但是這里面偏偏還夾雜好多其他的概念--變量提升啊...

    whataa 評(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
  • JavaScript之例題中徹底理解this

    摘要:最后重點(diǎn)理解結(jié)論箭頭函數(shù)的,總是指向定義時(shí)所在的對(duì)象,而不是運(yùn)行時(shí)所在的對(duì)象。輸出,箭頭函數(shù)不會(huì)綁定所以傳入指向無(wú)效。原因是,要徹底理解應(yīng)該是建立在已經(jīng)大致理解了中的執(zhí)行上下文,作用域作用域鏈,閉包,變量對(duì)象,函數(shù)執(zhí)行過(guò)程的基礎(chǔ)上。 本文共 2025 字,看完只需 8 分鐘 概述 前面的文章講解了 JavaScript 中的執(zhí)行上下文,作用域,變量對(duì)象,this 的相關(guān)原理,但是我...

    Hwg 評(píng)論0 收藏0
  • 初學(xué)者徹底理解javascript閉包以及this關(guān)鍵字

    摘要:理解了這句話(huà),我們就可以來(lái)看閉包了閉包前面說(shuō)過(guò),函數(shù)可以訪(fǎng)問(wèn)函數(shù)作用域鏈中的變量,但如果我們想在函數(shù)外訪(fǎng)問(wèn)函數(shù)內(nèi)卻不行了。 不管是閉包還是this關(guān)鍵字,都是困擾JS初學(xué)者的比較難懂的東西,如果你對(duì)它們的認(rèn)識(shí)還不足夠清晰,那么現(xiàn)在就一起把它們掌握掉。還是那句話(huà),我們從最基本的開(kāi)始,建立起一個(gè)非常清晰的知識(shí)結(jié)構(gòu),好了,開(kāi)始吧 ? 閉包 當(dāng)然我們今天說(shuō)的是javascript里的閉包。要學(xué)...

    魏明 評(píng)論0 收藏0
  • Javascript】深入理解this作用域問(wèn)題以及new/let/var/const對(duì)this作

    摘要:理解作用域高級(jí)程序設(shè)計(jì)中有說(shuō)到對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的在全局函數(shù)中,等于,而當(dāng)函數(shù)被作為某個(gè)對(duì)象調(diào)用時(shí),等于那個(gè)對(duì)象。指向與匿名函數(shù)沒(méi)有關(guān)系如果函數(shù)獨(dú)立調(diào)用,那么該函數(shù)內(nèi)部的,則指向。 理解this作用域 《javascript高級(jí)程序設(shè)計(jì)》中有說(shuō)到: this對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的:在全局函數(shù)中,this等于window,而當(dāng)函數(shù)被作為某個(gè)對(duì)象調(diào)用時(shí),t...

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

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

0條評(píng)論

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