摘要:一系列活動的執行上下文從邏輯上形成一個棧。棧底總是全局上下文,棧頂是當前活動的執行上下文。同樣的,當拋出未捕獲的異常時,也會退出一個或者多個執行上下文,也會做相應的退棧操作。
概要
本文將向大家介紹ECMAScript的執行上下文以及相關的可執行代碼類型。
定義每當控制器到達ECMAScript可執行代碼的時候,控制器就進入了一個執行上下文。
執行上下文(簡稱:EC)是個抽象的概念,ECMA-262標準中用它來區分不同類型的可執行代碼。
標準中并沒有從技術實現的角度來定義執行上下文的具體結構和類型;這是實現標準的ECMAScript引擎所要考慮的問題。
一系列活動的執行上下文從邏輯上形成一個棧。棧底總是全局上下文,棧頂是當前(活動的)執行上下文。當在不同的執行上下文間切換(退出的而進入新的執行上下文)的時候,棧會被修改(通過壓棧或者退棧的形式)。
可執行代碼類型可執行代碼類型和執行上下文相關。有的時候,當提到代碼類型的時候,其實就是在說執行上下文。
舉個例子,我們將執行上下文的棧以數組的形式來表示:
ECStask = [ ];
每次控制器進入一個函數(哪怕該函數被遞歸調用或者作為構造器),都會發生壓棧的操作。內置eval函數工作的時候也不例外。
全局代碼這類代碼是在“程序”級別上被處理的:比如,加載一個外部的js文件或者內聯的js代碼(被包含在標簽內)。全局代碼不包含任何函數體內的代碼。
在初始化的時候(程序開始),ECStack如下所示:
ECStack = [ globalContext ];函數代碼
一旦控制器進入函數代碼(各類函數),就會有新的元素會被壓棧到ECStack。要注意的是:實體函數代碼并不包括內部函數的代碼。如下所示,我們調用一個函數,該函數遞歸調用自己一次:
(function foo(bar){ if (bar){ return; } foo(true); })();
之后,ECStack就被修改成如下所示:
//首先激活foo函數 ECStack = [ functionContext globalContext ]; //遞歸激活foo函數 ECStack = [ functionContext - recursively functionContext globalContext ];
每次函數返回,退出當前活動的執行上下文時,ECStack就會被執行對應的退棧操作——先進后出——和傳統的棧實現一致。同樣的,當拋出未捕獲的異常時,也會退出一個或者多個執行上下文,ECStack也會做相應的退棧操作。待這些代碼完成之后,ECStack中就只剩下一個執行上下文(globalContext)——直到整個程序結束。
Eval代碼說到eval代碼就比較有意思了。這里要提到一個叫做調用上下文的概念,比如:調用eval函數時候的上下文,就是一個調用上下文,eval函數中執行的動作(例如:變量聲明或者函數聲明)會影響整個調用上下文:
eval(‘var x = 10’); (function foo(){ eval(‘ var y = 20’); })(); alert(x); // 10 alert(y); // ”y” is not defined
ECStack會被修改為:
ECStack = [ globalContext ]; //eval(‘var x = 10’); ECStack.push( evalContext, callingContext: globalContext ); // eval exited context ECStack.pop(); //foo function call ECStack.push( functionContext); //eval(‘ var y = 20’); ECStack.push( evalContext, callingContext: functionContext ); //return from eval ECStack.pop(); //return from foo ECStack.pop();
在1.7以上版本SpiderMonkey的實現中(Firefox,Thunderbird瀏覽器內置的JS引擎),允許在調用eval函數的時候,將調用上下文作為第二個參數傳遞給eval函數。因此,如果傳入的調用上下文存在的話,就有可能會影響該上下文中原有的私有變量(在該上下文中聲明的變量):
function foo(){ var x = 1; return function() { alert(x); } }; var bar = foo(); bar(); // 1 eval(‘x = 2’, bar); //傳遞上下文,影響了內部變量“var x” bar(); // 2總結
這些基本理論對于后面執行上下文相關的細節(諸如變量對象、作用域鏈等等)分析是非常必要的。
擴展閱讀ECMA-363-3標準文檔的對應的章節—— 10. 執行上下文
via 前端翻譯小站
趙靜(goddyzhao)譯自 Dmitry A.Soshnikov的文章Execution Context
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85448.html
摘要:引擎的運行原理引擎也是程序,是屬于瀏覽器的一部分,由瀏覽器廠商自行開發。為了提高運行速度,現代瀏覽器一般采用即時編譯即字節碼只在運行時編譯,用到哪一行就編譯哪一行,并且把編譯結果緩存這樣整個程序的運行速度能得到顯著提升。 相信大家在面試的過程中經常遇到查看執行順序的問題,如setTimeout,promise,async await等等,各種組合,是不是感覺頭都要暈掉了,其實這些問題最...
摘要:引擎的運行原理引擎也是程序,是屬于瀏覽器的一部分,由瀏覽器廠商自行開發。為了提高運行速度,現代瀏覽器一般采用即時編譯即字節碼只在運行時編譯,用到哪一行就編譯哪一行,并且把編譯結果緩存這樣整個程序的運行速度能得到顯著提升。 相信大家在面試的過程中經常遇到查看執行順序的問題,如setTimeout,promise,async await等等,各種組合,是不是感覺頭都要暈掉了,其實這些問題最...
摘要:延長作用域鏈下面兩種語句可以在作用域鏈的前端臨時增加一個變量對象以延長作用域鏈, 問題 今天看筆記發現自己之前記了一個關于同名標識符優先級的內容,具體是下面這樣的: 形參優先級高于當前函數名,低于內部函數名 形參優先級高于arguments 形參優先級高于只聲明卻未賦值的局部變量,但是低于聲明且賦值的局部變量 函數和變量都會聲明提升,函數名和變量名同名時,函數名的優先級要高。執行代...
摘要:所以覺得把這個執行的詳細過程整理一下,幫助更好的理解。類似的語法報錯的如下圖所示三預編譯階段代碼塊通過語法分析階段之后,語法都正確的下回進入預編譯階段。另開出新文章詳細分析,主要介紹執行階段中的同步任務執行和異步任務執行機制事件循環。 一、概述 js是一種非常靈活的語言,理解js引擎的執行過程對于我們學習js是非常有必要的??戳撕芏噙@方便文章,大多數是講的是事件循環(event loo...
摘要:關鍵字計算為當前執行上下文的屬性的值。毫無疑問它將指向了這個前置的對象。構造函數也是同理。嚴格模式無論調用位置,只取顯式給定的上下文綁定的,通過方法傳入的第一參數,否則是。其實并不屬于特殊規則,是由于各種事件監聽定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個關鍵字,它的值指向了一個對象的引用。這個引用的結果非常容易引起開發者的誤判,所以必須對這個關...
閱讀 733·2021-11-17 09:33
閱讀 3766·2021-09-01 10:46
閱讀 1758·2019-08-30 11:02
閱讀 3288·2019-08-29 15:05
閱讀 1404·2019-08-26 11:39
閱讀 2280·2019-08-23 17:04
閱讀 1980·2019-08-23 15:43
閱讀 1378·2019-08-23 14:12