寫在前面
首先,這系列文章是來自俄國某大神的部落格。dmitrysoshnikov.com/
其次,其實在網上已經有了此係列的翻譯文章。本人原本只想做個搬運工,So,不要說我抄襲什麼的感謝了!
介紹
這篇文章我們將介紹ECMAScript的執行上下文和與執行上下文相關的可執行程式碼型別。
定義
每當控制器進入一段ECMAScript的可執行程式碼時,控制器就進入了一個執行上下文。標準中並沒有準確定義執行上下文(縮寫為EC(Execution context))的結構和型別,這對ECMAScript執行引擎來說是一個問題。
活動的執行上下文被描述成一個棧,棧底總是全域性上下文,棧頂總是當前(被啟用)的執行上下文。棧的修改(即: 進棧/出棧)發生在進入一個新的執行上下文與退出一個正在執行的執行上下文(有點拗口)。
可執行程式碼的型別
我們抽象出來的關於可執行上下文的概念,其型別與可執行程式碼有關。我們的執行上下文其實就是在說可執行程式碼的型別。
舉個例子,我們把執行上下文的棧抽象成一個陣列:
ECStack = [];
複製程式碼
這個陣列被push是在進入一個新的執行上下文時發生(即使是函式的遞迴或者作為一個建構函式)。
全域性程式碼
這類程式碼是在“程式”級別上被處理的:比如,載入一個外部的js檔案或者內聯的js程式碼(被包含在標籤內)。全域性程式碼不包含任何函式體內的程式碼。
在程式初始化的時候。ECStack變成這樣:
ECStack = [
globalContext
];
複製程式碼
函式程式碼
在每次執行到函式程式碼時(各種各樣的函式),ECStack就會push進去其函式執行上下文。有必要注意的是:函式內部的程式碼跟這個上下文沒有任何關係。
舉個例子,讓我們看一個函式,其呼叫自己。
(function foo(flag) {
if (flag) {
return;
}
foo(true);
})(false);
複製程式碼
然後我們可以看到ECStack被修改成這樣:
//外部foo函式被啟用時
ECStack = [
<foo> functionContext
globalContext
];
//內部foo函式被啟用時
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];
複製程式碼
函式每次return時或者執行完時,其執行上下文就會退出,ECStack會相應的彈出這個執行上下文,然後很多次的進棧、出棧,最後直到所有可執行程式碼被執行完以後,只剩globalContext。
(eval的部分也很有意思,只不過認為不常用,所以不寫出來)
結論
這篇文章對系列文章中的“變數物件”、“作用域鏈”都很重要,希望可以深入理解掌握。