在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 執(zhí)行上下文(Execution Contexts)
代碼復用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設計模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設計模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設計模式之中介者模式
設計模式之裝飾者模式
設計模式之模板方法
設計模式之外觀模式
強大的原型和原型鏈
設計模式之構造函數模式
揭秘命名函數表達式
深入理解J avaScript 系列(結局篇)
執(zhí)行上下文(Execution Contexts)
函數(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設計模式之適配器模式
設計模式之組合模式
設計模式之命令模式
S.O.L.I.D 五大原則之單一職責 SRP
編寫高質量 JavaScript 代碼的基本要點
求值策略
閉包(Closures)
對象創(chuàng)建模式(上篇)
This? Yes,this!
設計模式之代理模式
變量對象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向對象編程之一般理論
設計模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設計模式之迭代器模式
立即調用的函數表達式
設計模式之享元模式
設計模式之原型模式
根本沒有“JSON 對象”這回事!
JavaScript 與 DOM(下)
面向對象編程之 ECMAScript 實現(xiàn)
全面解析 Module 模式
對象創(chuàng)建模式(下篇)
設計模式之職責鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設計模式之橋接模式
設計模式之策略模式
設計模式之觀察者模式
代碼復用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設計模式之工廠模式

執(zhí)行上下文(Execution Contexts)

簡介

從本章開始,我將陸續(xù)(翻譯、轉載、整理)http://dmitrysoshnikov.com/網站關于 ECMAScript 標標準理解的好文。

定義

每次當控制器轉到 ECMAScript 可執(zhí)行代碼的時候,即會進入到一個執(zhí)行上下文。執(zhí)行上下文(簡稱-EC)是 ECMA-262 標準里的一個抽象概念,用于同可執(zhí)行代碼(executable code)概念進行區(qū)分。

標準規(guī)范沒有從技術實現(xiàn)的角度定義EC的準確類型和結構,這應該是具體實現(xiàn) ECMAScript 引擎時要考慮的問題。

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

可執(zhí)行代碼類型

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

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

ECStack = [];

每次進入 function (即使 function 被遞歸調用或作為構造函數) 的時候或者內置的 eval 函數工作的時候,這個堆棧都會被壓入。

全局代碼

這種類型的代碼是在"程序"級處理的:例如加載外部的 js 文件或者本地標簽內的代碼。全局代碼不包括任何 function 體內的代碼。

在初始化(程序啟動)階段,ECStack 是這樣的:

ECStack = [
  globalContext
];

函數代碼

當進入 funtion 函數代碼(所有類型的 funtions)的時候,ECStack 被壓入新元素。需要注意的是,具體的函數代碼不包括內部函數(inner functions)代碼。如下所示,我們使函數自己調自己的方式遞歸一次:

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

那么,ECStack 以如下方式被改變:

// 第一次foo的激活調用
ECStack = [
  <foo> functionContext
  globalContext
];
// foo的遞歸激活調用
ECStack = [
  <foo> functionContext – recursively
  <foo> functionContext
  globalContext
];

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

Eval 代碼

eval 代碼有點兒意思。它有一個概念: 調用上下文(calling context),例如,eval 函數調用的時候產生的上下文。eval(變量或函數聲明)活動會影響調用上下文(calling context)。

eval('var x = 10');
(function foo() {
  eval('var y = 20');
})();
alert(x); // 10
alert(y); // "y" 提示沒有聲明

ECStac k的變化過程:

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();

也就是一個非常普通的邏輯調用堆棧。

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

function foo() {
  var x = 1;
  return function () { alert(x); };
};
var bar = foo();
bar(); // 1
eval('x = 2', bar); // 傳入上下文,影響了內部的var x 變量
bar(); // 2

結論

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

其他參考

這篇文章的內容在 ECMA-262-3 標準規(guī)范中對應的章節(jié)— 10. Execution Contexts。