摘要:不同執(zhí)行上下文中的變量對(duì)象對(duì)于所有的執(zhí)行上下文類型,變量對(duì)象的一些操作比如變量實(shí)例化和行為是共通的。從這點(diǎn)看,將變量對(duì)象看作是抽象的基礎(chǔ)的東西很便利。全局上下文的變量對(duì)象現(xiàn)在,應(yīng)該先給出全局對(duì)象的定義。
原文地址
作者的話有很多文章已經(jīng)對(duì)ECMAScript的核心概念做了詳盡解讀。本系列文章翻譯自Dmitry Soshnikov的個(gè)人網(wǎng)站,相信不少人已經(jīng)看過原文或者譯文。原文簡(jiǎn)潔易懂并且嚴(yán)謹(jǐn),條理清晰地闡明了所有JavaScript開發(fā)者不得不深入理解的ECMAScript核心概念。重復(fù)翻譯的原因主要是為了個(gè)人收藏、整理之用。初次翻譯,技巧拙劣,如有不足,請(qǐng)不吝賜教。
正文介紹
數(shù)據(jù)聲明
不同執(zhí)行上下文中的變量對(duì)象
全局上下文中的變量對(duì)象
函數(shù)上下文中的變量對(duì)象
處理上下文代碼的階段
進(jìn)入執(zhí)行上下文
代碼執(zhí)行
關(guān)于變量
實(shí)現(xiàn)的特點(diǎn):__parent__屬性
結(jié)論
介紹我們總是在程序中聲明函數(shù)和變量,然后成功地用作構(gòu)建我們的系統(tǒng)。但是,解釋器怎樣以及在哪里找到我們的數(shù)據(jù)(函數(shù)和變量)?當(dāng)我們引用需要的對(duì)象的時(shí)候發(fā)生了什么?
許多ECMAScript開發(fā)者知道變量和執(zhí)行上下文緊密相關(guān)。
var a = 10; // variable of the global context (function () { var b = 20; // local variable of the function context })(); alert(a); // 10 alert(b); // "b" is not defined
同時(shí),許多程序員也知道當(dāng)前版本(ES6之前,譯者注)的標(biāo)準(zhǔn)的獨(dú)立作用域是通過“函數(shù)”代碼類型的執(zhí)行上下文創(chuàng)建的。比如,和C/C++相反,ECMAScript中的for循環(huán)塊不會(huì)創(chuàng)建本地上下文。
for (var k in {a: 1, b: 2}) { alert(k); } alert(k); // variable "k" still in scope even the loop is finished
讓我們看看當(dāng)我們聲明數(shù)據(jù)時(shí)的所發(fā)生的細(xì)節(jié)。
數(shù)據(jù)聲明如果變量和執(zhí)行上下文相關(guān),那么應(yīng)該知道變量的數(shù)據(jù)存在哪里以及如何獲取它們。這個(gè)機(jī)制被稱為變量對(duì)象
變量對(duì)象(簡(jiǎn)稱:VO)是一個(gè)與執(zhí)行上下文相關(guān)的特殊對(duì)象,它存儲(chǔ)了在上下文中聲明的:
變量
函數(shù)聲明
函數(shù)形參
注意,在ES5中,變量對(duì)象的概念已經(jīng)被詞法環(huán)境模式取代,可以在適當(dāng)?shù)恼鹿?jié)找到它的詳細(xì)描述。
示意性的舉個(gè)例子,可以將變量對(duì)象表示成一個(gè)普通的ECMAScript對(duì)象:
VO = {};
正如我們所說,VO是執(zhí)行上下文的屬性:
activeExecutionContext = { VO: { // context data (var, FD, function arguments) } };
只允許在全局上下文(全局對(duì)象就是變量對(duì)象的地方)中,對(duì)變量間接引用(通過VO的屬性名)。對(duì)于其他上下文,對(duì)VO對(duì)象的直接引用是不可能的,這純粹是實(shí)現(xiàn)機(jī)制。
當(dāng)我們聲明了一個(gè)變量或函數(shù),除了使用我們的變量的名字和值創(chuàng)建VO的新屬性,沒別的了。
比如:
var a = 10; function test(x) { var b = 20; }; test(30);
相應(yīng)的變量對(duì)象是這樣:
// Variable object of the global context VO(globalContext) = { a: 10, test:}; // Variable object of the "test" function context VO(test functionContext) = { x: 30, b: 20 };
但是在實(shí)現(xiàn)層面(以及規(guī)范)中,變量對(duì)象是一個(gè)抽象的概念。物理上,在具體的執(zhí)行上下文中,VO被叫做不同的名稱,有不同的初始結(jié)構(gòu)。
不同執(zhí)行上下文中的變量對(duì)象對(duì)于所有的執(zhí)行上下文類型,變量對(duì)象的一些操作(比如變量實(shí)例化)和行為是共通的。從這點(diǎn)看,將變量對(duì)象看作是抽象的基礎(chǔ)的東西很便利。函數(shù)上下文也可以定義與變量對(duì)象相關(guān)的額外內(nèi)容。
AbstractVO (generic behavior of the variable instantiation process) ║ ╠══> GlobalContextVO ║ (VO === this === global) ║ ╚══> FunctionContextVO (VO === AO,object and are added)
我們?cè)敿?xì)解讀一下。
全局上下文的變量對(duì)象現(xiàn)在,應(yīng)該先給出全局對(duì)象的定義。
全局對(duì)象是在進(jìn)入任何執(zhí)行上下文前創(chuàng)建的對(duì)象;這個(gè)對(duì)象僅存在一份,它的屬性可以在程序的任何位置訪問到,全局對(duì)象的生命周期伴隨著程序結(jié)束而結(jié)束。
在創(chuàng)建時(shí),全局對(duì)象使用諸如:Math、String、Date、parseInt等初始化,也可以使用附加對(duì)象初始化,附加對(duì)象可以是全局對(duì)象本身的引用--比如在BOM中,全局對(duì)象的window屬性引用全局對(duì)象(不是在所有的實(shí)現(xiàn)中都是如此)。
global = { Math: <...>, String: <...> ... ... window: global };
當(dāng)引用全局對(duì)象的屬性,前綴往往可以省略,因?yàn)槿謱?duì)象不能通過名字直接訪問到。然而,在全局上下文中可以通過this值訪問到它,也可以通過對(duì)它的遞歸引用訪問到它,比如BOM中的window,因此可以簡(jiǎn)寫:
String(10); // means global.String(10); // with prefixes window.a = 10; // === global.window.a = 10 === global.a = 10; this.b = 20; // global.b = 20;
所以回到全局上下文的變量對(duì)象,這里變量對(duì)象就是全局對(duì)象本身:
VO(globalContext) === global;
很有必要理解這個(gè)事實(shí),由于這個(gè)原因,在全局上下文中聲明一個(gè)變量,我們可以通過全局對(duì)象的屬性間接訪問它(比如,當(dāng)變量名事先未知時(shí)):
var a = new String("test"); alert(a); // directly, is found in VO(globalContext): "test" alert(window["a"]); // indirectly via global === VO(globalContext): "test" alert(a === this.a); // true var aKey = "a"; alert(window[aKey]); // indirectly, with dynamic property name: "test"函數(shù)上下文的變量對(duì)象
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96863.html
摘要:邏輯上講,活躍的執(zhí)行上下文集合組成了一個(gè)棧。棧底是全局上下文,棧頂是當(dāng)前活躍執(zhí)行上下文。舉個(gè)例子,我們將執(zhí)行上下文定義成一個(gè)數(shù)組。一個(gè)拋出但是沒有捕獲的異??赡軐?dǎo)致退出一個(gè)或多個(gè)執(zhí)行上下文代碼代碼更加復(fù)雜。 原文地址 作者的話 有很多文章已經(jīng)對(duì)ECMAScript的核心概念做了詳盡解讀。本系列文章翻譯自Dmitry Soshnikov的個(gè)人網(wǎng)站,相信不少人已經(jīng)看過原文或者譯文。原文簡(jiǎn)潔...
摘要:如果在全局代碼中調(diào)用函數(shù),程序的順序流進(jìn)入被調(diào)用的函數(shù),創(chuàng)建新的執(zhí)行上下文并將其推送到執(zhí)行堆棧的頂部。每次調(diào)用函數(shù)時(shí),都會(huì)創(chuàng)建一個(gè)新的執(zhí)行上下文。 翻譯:瘋狂的技術(shù)宅鏈接:http://davidshariff.com/blog/... 本文首發(fā)微信公眾號(hào):jingchengyideng歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 在這篇文章中,我將深入探討JavaScript的最...
摘要:堆棧結(jié)構(gòu)的底部是全局執(zhí)行上下文,頂部是當(dāng)前執(zhí)行上下文。不同的執(zhí)行上下文切換時(shí)堆棧會(huì)發(fā)生改變譯論及代碼類型時(shí),在某些時(shí)候可能也意味著執(zhí)行上下文。函數(shù)體中代碼執(zhí)行完后,只剩全局上下文直到程序結(jié)束譯代碼更有意思。 第一次翻譯,希望各位多多包涵,有錯(cuò)誤處還望指出,歡迎提出建議。 Chapter 1.Execution Contexts Introduction (介紹) Definitio...
摘要:前言大家學(xué)的時(shí)候,經(jīng)常遇到自執(zhí)行匿名函數(shù)的代碼,今天我們主要就來想想說一下自執(zhí)行。其實(shí),前面兩個(gè)例子里的變量,也可以換成,因?yàn)楹屯饷娴牟辉谝粋€(gè)作用于,所以不會(huì)出現(xiàn)問題,這也是匿名函數(shù)閉包的威力。 前言 大家學(xué)JavaScript的時(shí)候,經(jīng)常遇到自執(zhí)行匿名函數(shù)的代碼,今天我們主要就來想想說一下自執(zhí)行。 在詳細(xì)了解這個(gè)之前,我們來談了解一下自執(zhí)行這個(gè)叫法,本文對(duì)這個(gè)功能的叫法也不一定完全對(duì)...
摘要:然后最后一步就是從父作用域鏈中將該特殊對(duì)象刪除,整個(gè)過程的偽代碼如下注意這里,該屬性不能刪除,只讀。 起因是我在逛sf的時(shí)候看到了一個(gè)人的提問: 為什么將函數(shù)c賦值給變量b,在函數(shù)體里面,給c賦值,為什么會(huì)失?。恳簿褪沁@代碼執(zhí)行時(shí)為什么c打印出來的不是3 var b = function c () { a=1, b=2, c=3; console.log(a); ...
閱讀 3551·2021-11-23 10:10
閱讀 3320·2019-08-30 14:03
閱讀 2077·2019-08-30 13:09
閱讀 3404·2019-08-29 15:29
閱讀 1550·2019-08-29 11:23
閱讀 2017·2019-08-28 18:28
閱讀 2853·2019-08-26 13:34
閱讀 2175·2019-08-26 11:32