最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解JavaScript系列(11) 執(zhí)行上下文(Execution Contexts)

 更新時(shí)間:2012年01月15日 23:44:23   作者:  
本章我們要講解的是ECMAScript標(biāo)準(zhǔn)里的執(zhí)行上下文和相關(guān)可執(zhí)行代碼的各種類型
簡介
從本章開始,我將陸續(xù)(翻譯、轉(zhuǎn)載、整理)http://dmitrysoshnikov.com/網(wǎng)站關(guān)于ECMAScript標(biāo)標(biāo)準(zhǔn)理解的好文。

本章我們要講解的是ECMAScript標(biāo)準(zhǔn)里的執(zhí)行上下文和相關(guān)可執(zhí)行代碼的各種類型。

原始作者:Dmitry A. Soshnikov
原始發(fā)布: 2009-06-26
俄文原文:http://dmitrysoshnikov.com/ecmascript/ru-chapter-1-execution-contexts/

英文翻譯:Dmitry A. Soshnikov.
發(fā)布時(shí)間:2010-03-11
英文翻譯:http://dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts/

本文參考了博客園justinw的中文翻譯,做了一些錯(cuò)誤修正,感謝譯者。
復(fù)制代碼
定義
每次當(dāng)控制器轉(zhuǎn)到ECMAScript可執(zhí)行代碼的時(shí)候,即會(huì)進(jìn)入到一個(gè)執(zhí)行上下文。執(zhí)行上下文(簡稱-EC)是ECMA-262標(biāo)準(zhǔn)里的一個(gè)抽象概念,用于同可執(zhí)行代碼(executable code)概念進(jìn)行區(qū)分。

標(biāo)準(zhǔn)規(guī)范沒有從技術(shù)實(shí)現(xiàn)的角度定義EC的準(zhǔn)確類型和結(jié)構(gòu),這應(yīng)該是具體實(shí)現(xiàn)ECMAScript引擎時(shí)要考慮的問題。

活動(dòng)的執(zhí)行上下文組在邏輯上組成一個(gè)堆棧。堆棧底部永遠(yuǎn)都是全局上下文(global context),而頂部就是當(dāng)前(活動(dòng)的)執(zhí)行上下文。堆棧在EC類型進(jìn)入和退出上下文的時(shí)候被修改(推入或彈出)。

可執(zhí)行代碼類型
可執(zhí)行代碼的類型這個(gè)概念與執(zhí)行上下文的抽象概念是有關(guān)系的。在某些時(shí)刻,可執(zhí)行代碼與執(zhí)行上下文完全有可能是等價(jià)的。

例如,我們可以定義執(zhí)行上下文堆棧是一個(gè)數(shù)組:

ECStack = [];
每次進(jìn)入function (即使function被遞歸調(diào)用或作為構(gòu)造函數(shù)) 的時(shí)候或者內(nèi)置的eval函數(shù)工作的時(shí)候,這個(gè)堆棧都會(huì)被壓入。

全局代碼
這種類型的代碼是在"程序"級處理的:例如加載外部的js文件或者本地<script></script>標(biāo)簽內(nèi)的代碼。全局代碼不包括任何function體內(nèi)的代碼。

在初始化(程序啟動(dòng))階段,ECStack是這樣的:
復(fù)制代碼 代碼如下:

ECStack = [
globalContext
];

函數(shù)代碼
當(dāng)進(jìn)入funtion函數(shù)代碼(所有類型的funtions)的時(shí)候,ECStack被壓入新元素。需要注意的是,具體的函數(shù)代碼不包括內(nèi)部函數(shù)(inner functions)代碼。如下所示,我們使函數(shù)自己調(diào)自己的方式遞歸一次:
復(fù)制代碼 代碼如下:

(function foo(bar) {
if (bar) {
return;
}
foo(true);
})();

那么,ECStack以如下方式被改變:
復(fù)制代碼 代碼如下:

// 第一次foo的激活調(diào)用
ECStack = [
<foo> functionContext
globalContext
];

// foo的遞歸激活調(diào)用
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];

每次return的時(shí)候,都會(huì)退出當(dāng)前執(zhí)行上下文的,相應(yīng)地ECStack就會(huì)彈出,棧指針會(huì)自動(dòng)移動(dòng)位置,這是一個(gè)典型的堆棧實(shí)現(xiàn)方式。一個(gè)拋出的異常如果沒被截獲的話也有可能從一個(gè)或多個(gè)執(zhí)行上下文退出。相關(guān)代碼執(zhí)行完以后,ECStack只會(huì)包含全局上下文(global context),一直到整個(gè)應(yīng)用程序結(jié)束。

Eval 代碼
eval 代碼有點(diǎn)兒意思。它有一個(gè)概念: 調(diào)用上下文(calling context),例如,eval函數(shù)調(diào)用的時(shí)候產(chǎn)生的上下文。eval(變量或函數(shù)聲明)活動(dòng)會(huì)影響調(diào)用上下文(calling context)。
復(fù)制代碼 代碼如下:

eval('var x = 10');

(function foo() {
eval('var y = 20');
})();

alert(x); // 10
alert(y); // "y" 提示沒有聲明

ECStack的變化過程:
復(fù)制代碼 代碼如下:

ECStack = [
globalContext
];

// eval('var x = 10');
ECStack.push(
evalContext,
callingContext: globalContext
);

// eval exited context
ECStack.pop();

// foo funciton call
ECStack.push(<foo> functionContext);

// eval('var y = 20');
ECStack.push(
evalContext,
callingContext: <foo> functionContext
);

// return from eval
ECStack.pop();

// return from foo
ECStack.pop();

也就是一個(gè)非常普通的邏輯調(diào)用堆棧。

在版本號1.7以上的SpiderMonkey(內(nèi)置于Firefox,Thunderbird)的實(shí)現(xiàn)中,可以把調(diào)用上下文作為第二個(gè)參數(shù)傳遞給eval。那么,如果這個(gè)上下文存在,就有可能影響“私有”(有人喜歡這樣叫它)變量。
復(fù)制代碼 代碼如下:

function foo() {
var x = 1;
return function () { alert(x); };
};

var bar = foo();

bar(); // 1

eval('x = 2', bar); // 傳入上下文,影響了內(nèi)部的var x 變量

bar(); // 2

結(jié)論
這篇文章是后面分析其他跟執(zhí)行上下文相關(guān)的主題(例如變量對象,作用域鏈,等等)的最起碼的理論基礎(chǔ),這些主題將在后續(xù)章節(jié)中講到。

其他參考

相關(guān)文章

最新評論

旬阳县| 介休市| 麻栗坡县| 杂多县| 锡林郭勒盟| 屯昌县| 广安市| 紫金县| 灵山县| 新和县| 镇远县| 色达县| 金昌市| 日照市| 榆社县| 区。| 全州县| 炉霍县| 洛宁县| 营口市| 惠水县| 隆化县| 光山县| 山阳县| 包头市| 池州市| 称多县| 镇康县| 葫芦岛市| 华蓥市| 合水县| 大名县| 贵州省| 沁水县| 舒城县| 华坪县| 仲巴县| 洛隆县| 尉犁县| 敖汉旗| 遵化市|