JS學習系列 05 執行上下文

2021-09-11 12:51:21 字數 3008 閱讀 4804

在我們前面理解了作用域之後,「作用域鏈」這個概念就產生了。那麼作用域鏈是什麼意思,它又是怎麼形成的,跟哪些概念有關係,這就是我接下來幾章想和大家**的內容:執行上下文、變數物件和作用域鏈。根據順序我們也可以看出來,想要理解作用域鏈,執行上下文是我們碰到的第乙個坎。

這一章我們就來討論一下到底什麼是執行上下文

1. 定義

當 js 引擎開始執行預編譯生成的**時,就會進入到乙個執行上下文(executable code - 簡稱ec)。

在 ecma 標準規範裡並沒有從技術角度去定義 ec 的具體型別和結構,這個是在實現 ecmascript 引擎時需要考慮的問題。

但是在邏輯上,我們可以將活動的執行上下文看成乙個棧結構。棧底部永遠是全域性上下文(global context),而頂部就是當前活動的執行上下文。執行到當前**時,上下文入棧,執行完畢後,上下文出棧。

2. 可執行**有幾種

前面說到當引擎執行到可執行**的時候,就會將當前上下文壓入上下文棧中。那麼可執行的**又分為幾種?

在這裡,我們先假設定義執行上下文棧是乙個陣列:

ec = ;

複製**

第一種可執行** -- 全域性**:全域性型別**是在載入外部的 js 檔案或者本地 標籤中的**。注意,在全域性**中,並不包含定義在全域性環境 function 內的**

程式啟動後進入初始化全域性環境:

ec = [

globalcontext

];複製**

第二種可執行** -- 函式**:當定義的函式被執行時,就進入了函式**,當前函式上下文被壓入 ec 棧中。注意,在函式**中,也不包含定義在該函式內部環境 function 內的**。

例如:

var a = 10;

function

foo ()

foo();

複製**

這個例子中的 ec 是什麼樣子的呢?

// 初始化

ec = [

globalcontext

];// 第一次呼叫 foo 函式

ec = [

functioncontext,

globalcontext

];// 在 foo 內遞迴呼叫自己

ec = [

functioncontext - recursively,

functioncontext,

globalcontext

];// 繼續遞迴呼叫自己

ec = [

......

functioncontext - recursively2,

functioncontext - recursively,

functioncontext,

globalcontext

];// 遞迴會不斷呼叫下去,因為沒有結束條件,所以這是乙個死迴圈

// 所以,ec 只會不斷增加新的上下文,但是卻不會退出

複製**

只有每次return的時候,才會退出當前執行上下文,相應上下文會從棧中彈出,棧指標會自動移動位置。

注意,當函式沒有明確指明 return 什麼的時候,預設 return undefined

如果有丟擲的異常沒有被截獲的話,也有可能從乙個或多個執行上下文中退出。當所有**執行完以後,ec 中只會包含全域性上下文(global context),當程式退出以後,全域性上下文也會退出。

第三種可執行** -- eval **:eval 函式在呼叫的時候會產生上下文。 例如:

eval('var a = 10');

(function

foo () ());

alert(a); // 10

alert(b); // referenceerror,b is not defined

複製**

這個例子中 ec 的變化如下:

// 初始化

ec = [

globalcontext

];// eval('var a = 10');

ec = [

evalcontext,

globalcontext

];// eval 執行完畢

ec = [

globalcontext

];// 立即執行函式 foo

ec = [

functioncontext,

globalcontext

];// eval('var b = 20');

ec = [

evalcontext,

functioncontext,

globalcontext

];// eval 執行完畢

ec = [

functioncontext,

globalcontext

];// foo 執行完畢

ec = [

globalcontext

];複製**

這就是乙個典型的邏輯呼叫上下文棧

在 settimeout 和 setinterval 函式中的第乙個引數也可以傳入**字串,但是這個一般不會這麼去用,所以這裡也就不討論了。

3. 結論

執行上下文環境是我們了解變數物件作用域鏈的基礎,大家一定要好好理解(其實也並不難),下一節我們來討論變數物件,相信會讓大家有一定的收穫。

JS學習系列 05 執行上下文

在我們前面理解了作用域之後,作用域鏈 這個概念就產生了。那麼作用域鏈是什麼意思,它又是怎麼形成的,跟哪些概念有關係,這就是我接下來幾章想和大家 的內容 執行上下文 變數物件和作用域鏈。根據順序我們也可以看出來,想要理解作用域鏈,執行上下文是我們碰到的第乙個坎。這一章我們就來討論一下到底什麼是執行上下...

Js系列三 執行上下文

js 在執行的時候會進入乙個特定的環境中,這個環境被稱為執行上下文。在js中執行環境主要包括以下三種情況 1 全域性環境既js 執行時首先進入的環境。2 函式環境 函式執行時會進入當前函式的環境執行 由此我們知道在js程式執行過程中必然會出現多個執行環境 執行上下文 js引擎以函式呼叫棧的方式來處理...

js執行上下文與執行上下文棧

在了解js的執行上下文物件與執行上下文棧之前,我們要先了解兩個概念 即變數提公升跟函式提公升 變數提公升 通過var定義的變數,在定義語句之前我們就可以直接訪問到,不過它的值是undefined 函式提公升 通過function定義的函式,在函式定義語句前,我們就可以直接呼叫 變數提公升與函式提公升...