在這一部分咱們將會說起js中的一些執行上下文(execution context),還有與執行上下文中相關聯的可執行代碼(executable code).數組
Execution Context是經過ECMA 262 規範用於Exectuable code的類型和區分的抽象概念。該標準並無從技術角度明肯定義Execution Context的種類和結構,該問題須要js引擎去實現。bash
從邏輯上講,執行上下文將會造成一個stack, stack的底部始終是global context,stack頂部老是當前active exection context 。每當進入或者退出執行上下文,這個stack就會被修改(pushed or popped)。函數
咱們將執行上下文定義成一個數組: ExecutionContextStack = [];1.每當加載外部的js文件時,或者進入<script></script>
標籤時,就會建立一個全局執行上下文; 當程序開始時,ECStack爲: ECStack = [ globalContext ]ui
2.每當調用一個function時,就會建立一個functionContext,可是並不包括內部函數的執行上下文或者遞歸調用的上下文,如下面代碼爲例:this
(function f(flag){
if(flag){
return;
}
f(true);
})(false);
複製代碼
接着ECStack就會發生變化:spa
1.當進入函數f時
ECStack = [
<f> functioncontext
globalContext
]
2.當遞歸調用自身時
ECStack = [
<f> functioncontext -> 遞歸調用
<f> functioncontext
globalContext
]
複製代碼
函數能夠被重複調用,故一個函數可能會產生多個執行上下文
function fn(a){
}
fn(1);
fn(2);
fn(3);
以上都是調用同一個函數,可是會產生三個執行上下文,而且三個執行上下文是有所不一樣的,其中變量對象中的arguments就不一樣,下一篇會有所說明
複製代碼
每當函數內部遇到return或者執行完畢時,當前的執行上下文就會從stack中退出,最後ECStack就剩下全局上下文了。那麼何時全局上下文也從stack中退出呢?當你退出整個程序(關閉文件)全局上下文就會從stack中退出。 舉個例子說明上述的過程:code
var a = 10;
function sayHello(){
console.log('hello')
}
sayHello()
複製代碼
1.第一步進入js代碼時,全局上下文就會被建立,該上下文會被推入到ECStack中;第二步當調用sayHello函數時,就會建立一個sayHello函數上下文,並將該上下文推入到ECStack中;以下圖: cdn
2.當sayHello函數的內部代碼執行完畢時,該函數上下文就會從ECStack中退出,此時ECStack中就剩下全局上下文了;當關閉文件時,全局上下文就會從ECStack中退出; 每個執行上下文均可當作是一個對象,都會有一些特定的屬性,至少包含三個值,variable object,scope chain ,this value。下一篇將會講執行上下文中的Variab Object對象