執行上下文(Execution Context)是JavaScript中一個非常重要的概念,它是程式碼執行時的環境資訊,包含了變數、函式、作用域等資訊。每當JavaScript引擎執行一段可執行程式碼時,都會建立一個執行上下文,該上下文會被壓入執行上下文棧中,當執行完畢後,該上下文將從棧中彈出。
一、執行上下文的階段
JavaScript程式的執行過程可以分為兩個階段,建立階段和執行階段。執行上下文的建立和執行也分別發生在這兩個階段中。
1.建立階段:在建立階段,JavaScript引擎會掃描整個程式碼,將變數宣告和函式宣告新增到變數物件中。此時,執行上下文的變數物件和作用域鏈已經建立,但是還未有詳細的值。
2.執行階段:在執行階段,JavaScript引擎會逐行執行程式碼,同時根據需要更新變數物件中的值,執行函式呼叫等操縱。在執行函式時,會建立函式執行上下文,並將其壓入執行上下文棧中。函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
可以看出,執行上下文的建立和執行發生在程式的不同階段,這也反映了JavaScript語言的特性:動態、解釋性、基於物件等。在編寫JavaScript程式時,需要了解執行上下文的概念和工作原理,以便更好地理解JavaScript的執行機制和除錯程式。

建立階段
執行上下文的建立階段是JavaScript引擎在執行JavaScript程式之前,對程式進行掃描和處理的階段。在建立階段,JavaScript引擎會完成以下幾個任務:
1.建立變數物件(Variable Object):JavaScript引擎會建立當前執行上下文的變數物件,用於儲存變數和函式宣告。對於全域性執行上下文來說,變數物件就是全域性物件(例如window物件);對於函式執行上下文來說,變數物件包括函式引數、內部變數和函式宣告等。
2.建立作用域鏈(Scope Chain):作用域鏈是由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。JavaScript引擎會在建立階段建立作用域鏈,以便在執行階段使用。
3.確定this指向:在建立階段,JavaScript引擎會確定當前執行上下文的this指向。對於全域性執行上下文來說,this指向全域性物件;對於函式執行上下文來說,this指向呼叫該函式的物件。
需要留意的是,在建立階段變數物件已經被建立,但變數的值還沒有被賦予,因此在建立階段訪問變數時,變數的值為undefined。在執行階段,當變數的值被賦予後,變數的值就會被更新。
執行階段
執行上下文的執行階段是JavaScript引擎在編譯階段之後,對JavaScript程式進行逐行執行的階段。在執行階段,JavaScript引擎會完成以下幾個任務:
1.變數賦值:在執行階段,JavaScript引擎會逐行執行程式碼,並對變數進行賦值。假如變數還沒有被宣告,JavaScript引擎會丟擲ReferenceError異常。
2.函式呼叫:假如程式碼中包含函式呼叫,JavaScript引擎會建立新的函式執行上下文,並將其壓入執行上下文棧中。在函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,繼續執行上一個執行上下文。
3.閉包:在執行階段,假如函式內部引用了外部變數,就會形成閉包。JavaScript引擎會將外部變數的值留存在閉包中,以便在函式執行期間訪問。
4.垃圾回收:在執行階段,JavaScript引擎會按期執行垃圾回收,以便清理不再使用的記憶體。需要留意的是,執行階段是一個逐行執行的過程,一旦泛起錯誤,JavaScript引擎就會當即住手執行,並丟擲異常。因此,在編寫JavaScript程式時,需要留意程式碼的正確性和可讀性,以便更好地除錯程式。
二、執行上下文棧
執行上下文棧是JavaScript中治理執行上下文的一種資料結構,它用於跟蹤程式碼的執行,並治理程式碼執行時所需的上下文環境。執行上下文棧是一個後進先出(LIFO)的資料結構,即最後一個進入的執行上下文會被最先執行和彈出。
當JavaScript程式開始執行時,會建立全域性執行上下文,並將其壓入執行上下文棧中。跟著程式碼的執行,每當碰到一個函式呼叫語句,JavaScript引擎就會建立一個新的函式執行上下文,並將其壓入執行上下文棧中。當函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,並繼續執行上一個執行上下文。
執行上下文棧的頂部始終是當前正在執行的程式碼所在的執行上下文。當執行上下文棧為空時,JavaScript程式執行結束。
var a = 1;
function foo() {
var b = 2;
function bar() {
var c = 3;
console.log(a, b, c);
}
bar();
}
foo();
當該程式碼執行時,JavaScript引擎會建立執行上下文棧,並按照以下順序進行壓棧和出棧操縱:
1.建立全域性執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中只有全域性執行上下文。
2.執行到函式foo(),JavaScript引擎會建立函式foo()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
3.執行到函式bar(),JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:bar()執行上下文 -> foo()執行上下文 -> 全域性執行上下文。
4.函式bar()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
5.函式foo()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:全域性執行上下文。
6.程式執行結束,JavaScript引擎結束執行。
透過執行上下文棧的治理,JavaScript引擎可以跟蹤程式碼的執行過程,並及時建立和銷燬執行上下文環境,確保程式碼的準確執行和記憶體治理。
三、執行上下文的分類
執行上下文可以分為以下三種類型:
1.全域性執行上下文(Global Execution Context)
2.函式執行上下文(Function Execution Context)
3.Eval函式執行上下文(Eval Function Execution Context)
需要留意的是,每個執行上下文都會被建立成一個獨立的環境,並且在執行完畢後會被銷燬。在執行上下文銷燬之前,JavaScript引擎會對其進行垃圾回收,以便開釋不再使用的記憶體。
全域性執行上下文
全域性執行上下文是JavaScript程式執行時的預設執行上下文,它是整個程式的頂層執行上下文。當JavaScript程式開始執行時,JavaScript引擎會自動建立並壓入全域性執行上下文到執行上下文棧中。
全域性執行上下文包含了以下幾個部門:
1.全域性物件(Global Object):它是全域性執行上下文的變數物件,包含了所有全域性變數、全域性函式等資訊。在瀏覽器環境中,全域性物件就是window物件。
2.this值:在全域性執行上下文中,this指向全域性物件。在瀏覽器環境中,this指向window物件。
3.外部環境(Outer Environment):全域性執行上下文沒有外部環境,它的外部環境為null。
全域性執行上下文是整個JavaScript程式的進口,它在程式執行期間始終存在,直到程式結束。所有的變數、函式都會成為全域性物件的屬性,可以透過全域性物件來訪問它們。因此,在編寫JavaScript程式時,需要留意全域性變數的使用,避免命名衝突和全域性變數汙染。
函式執行上下文
函式執行上下文是當JavaScript引擎執行一個函式時,建立的一個執行上下文。每個函式都會有自己的函式執行上下文。
函式執行上下文包含了以下幾個部門:
1.變數物件(Variable Object):函式執行上下文的變數物件包含了所有函式引數、內部變數、函式宣告等資訊。
2.作用域鏈(Scope Chain):作用域鏈由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。
3.this值:this指向呼叫該函式的物件。
當函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
function foo(a, b) {
var c = 1;
function bar() {
var d = 2;
console.log(a, b, c, d);
}
bar();
}
foo(10, 20);
當該程式碼執行時,JavaScript引擎會建立函式執行上下文,包括變數環境、詞法環境和this指向等資訊,並將其壓入執行上下文棧中。
具體來說,函式foo()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中a和b為引數,c為區域性變數,d為函式bar()內部的區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式foo()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:在該程式碼中,函式foo()會呼叫內部的函式bar()。
當函式bar()被呼叫時,JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中。
具體來說,函式bar()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中d為區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式bar()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:函式bar()沒有再次呼叫其他函式。
當函式bar()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時函式foo()的執行上下文仍在執行上下文棧的頂部。
函式foo()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧為空,JavaScript程式執行結束。
Eval函式執行上下文
Eval函式執行上下文是在呼叫eval函式時建立的執行上下文。Eval函式可以動態地執行JavaScript程式碼,並且可以訪問當前執行上下文的變數和函式。Eval函式執行上下文可以形成巢狀的作用域鏈,但它通常會被以為是當前執行上下文的一部分,而不是一個單獨的執行上下文。
Eval函式是JavaScript中的一個內建函式,用於執行動態建立的JavaScript程式碼。下面是一個簡樸的Eval函式案例:
let x = 1;
let y = 2;
let code = "console.log(x + y);"; // 動態建立的程式碼
eval(code); // 輸出結果為3
在上面的例子中,我們建立了一個字串變數code,該變數儲存了要執行的程式碼,即輸出x和y的和。然後,我們呼叫了eval函式,將字串code作為引數傳入。eval函式將字串作為JavaScript程式碼執行,輸出了3。
需要留意的是,eval函式的使用應該非常小心,由於它會執行傳入的任意程式碼,可能會導致意料之外的結果,並且可能會有安全隱患。建議在使用eval函式時,必需要確保傳入的程式碼是可託的,避免執行惡意程式碼。
總結
執行上下文是JavaScript中一個重要的概念,用於描述程式碼執行時的環境。一個執行上下文可以看作是一個獨立的環境,包含了當前程式碼執行所需的所有資訊,如變數、函式、this指向等。JavaScript中有三種類型的執行上下文:全域性執行上下文、函式執行上下文和eval函式執行上下文。
執行上下文分為兩個階段:建立階段和執行階段。在建立階段,JavaScript引擎會對程式碼進行解析,並將變數和函式宣告新增到當前執行上下文的作用域中。在執行階段,JavaScript引擎會逐行執行程式碼,並完成變數賦值、函式呼叫、this指向、閉包和垃圾回收等任務。
執行上下文(Execution Context)是JavaScript中一個非常重要的概念,它是程式碼執行時的環境資訊,包含了變數、函式、作用域等資訊。每當JavaScript引擎執行一段可執行程式碼時,都會建立一個執行上下文,該上下文會被壓入執行上下文棧中,當執行完畢後,該上下文將從棧中彈出。
一、執行上下文的階段
JavaScript程式的執行過程可以分為兩個階段,建立階段和執行階段。執行上下文的建立和執行也分別發生在這兩個階段中。
1.建立階段:在建立階段,JavaScript引擎會掃描整個程式碼,將變數宣告和函式宣告新增到變數物件中。此時,執行上下文的變數物件和作用域鏈已經建立,但是還未有詳細的值。
2.執行階段:在執行階段,JavaScript引擎會逐行執行程式碼,同時根據需要更新變數物件中的值,執行函式呼叫等操縱。在執行函式時,會建立函式執行上下文,並將其壓入執行上下文棧中。函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
可以看出,執行上下文的建立和執行發生在程式的不同階段,這也反映了JavaScript語言的特性:動態、解釋性、基於物件等。在編寫JavaScript程式時,需要了解執行上下文的概念和工作原理,以便更好地理解JavaScript的執行機制和除錯程式。

建立階段
執行上下文的建立階段是JavaScript引擎在執行JavaScript程式之前,對程式進行掃描和處理的階段。在建立階段,JavaScript引擎會完成以下幾個任務:
1.建立變數物件(Variable Object):JavaScript引擎會建立當前執行上下文的變數物件,用於儲存變數和函式宣告。對於全域性執行上下文來說,變數物件就是全域性物件(例如window物件);對於函式執行上下文來說,變數物件包括函式引數、內部變數和函式宣告等。
2.建立作用域鏈(Scope Chain):作用域鏈是由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。JavaScript引擎會在建立階段建立作用域鏈,以便在執行階段使用。
3.確定this指向:在建立階段,JavaScript引擎會確定當前執行上下文的this指向。對於全域性執行上下文來說,this指向全域性物件;對於函式執行上下文來說,this指向呼叫該函式的物件。
需要留意的是,在建立階段變數物件已經被建立,但變數的值還沒有被賦予,因此在建立階段訪問變數時,變數的值為undefined。在執行階段,當變數的值被賦予後,變數的值就會被更新。
執行階段
執行上下文的執行階段是JavaScript引擎在編譯階段之後,對JavaScript程式進行逐行執行的階段。在執行階段,JavaScript引擎會完成以下幾個任務:
1.變數賦值:在執行階段,JavaScript引擎會逐行執行程式碼,並對變數進行賦值。假如變數還沒有被宣告,JavaScript引擎會丟擲ReferenceError異常。
2.函式呼叫:假如程式碼中包含函式呼叫,JavaScript引擎會建立新的函式執行上下文,並將其壓入執行上下文棧中。在函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,繼續執行上一個執行上下文。
3.閉包:在執行階段,假如函式內部引用了外部變數,就會形成閉包。JavaScript引擎會將外部變數的值留存在閉包中,以便在函式執行期間訪問。
4.垃圾回收:在執行階段,JavaScript引擎會按期執行垃圾回收,以便清理不再使用的記憶體。需要留意的是,執行階段是一個逐行執行的過程,一旦泛起錯誤,JavaScript引擎就會當即住手執行,並丟擲異常。因此,在編寫JavaScript程式時,需要留意程式碼的正確性和可讀性,以便更好地除錯程式。
二、執行上下文棧
執行上下文棧是JavaScript中治理執行上下文的一種資料結構,它用於跟蹤程式碼的執行,並治理程式碼執行時所需的上下文環境。執行上下文棧是一個後進先出(LIFO)的資料結構,即最後一個進入的執行上下文會被最先執行和彈出。
當JavaScript程式開始執行時,會建立全域性執行上下文,並將其壓入執行上下文棧中。跟著程式碼的執行,每當碰到一個函式呼叫語句,JavaScript引擎就會建立一個新的函式執行上下文,並將其壓入執行上下文棧中。當函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,並繼續執行上一個執行上下文。
執行上下文棧的頂部始終是當前正在執行的程式碼所在的執行上下文。當執行上下文棧為空時,JavaScript程式執行結束。
var a = 1;
function foo() {
var b = 2;
function bar() {
var c = 3;
console.log(a, b, c);
}
bar();
}
foo();
當該程式碼執行時,JavaScript引擎會建立執行上下文棧,並按照以下順序進行壓棧和出棧操縱:
1.建立全域性執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中只有全域性執行上下文。
2.執行到函式foo(),JavaScript引擎會建立函式foo()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
3.執行到函式bar(),JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:bar()執行上下文 -> foo()執行上下文 -> 全域性執行上下文。
4.函式bar()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
5.函式foo()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:全域性執行上下文。
6.程式執行結束,JavaScript引擎結束執行。
透過執行上下文棧的治理,JavaScript引擎可以跟蹤程式碼的執行過程,並及時建立和銷燬執行上下文環境,確保程式碼的準確執行和記憶體治理。
三、執行上下文的分類
執行上下文可以分為以下三種類型:
1.全域性執行上下文(Global Execution Context)
2.函式執行上下文(Function Execution Context)
3.Eval函式執行上下文(Eval Function Execution Context)
需要留意的是,每個執行上下文都會被建立成一個獨立的環境,並且在執行完畢後會被銷燬。在執行上下文銷燬之前,JavaScript引擎會對其進行垃圾回收,以便開釋不再使用的記憶體。
全域性執行上下文
全域性執行上下文是JavaScript程式執行時的預設執行上下文,它是整個程式的頂層執行上下文。當JavaScript程式開始執行時,JavaScript引擎會自動建立並壓入全域性執行上下文到執行上下文棧中。
全域性執行上下文包含了以下幾個部門:
1.全域性物件(Global Object):它是全域性執行上下文的變數物件,包含了所有全域性變數、全域性函式等資訊。在瀏覽器環境中,全域性物件就是window物件。
2.this值:在全域性執行上下文中,this指向全域性物件。在瀏覽器環境中,this指向window物件。
3.外部環境(Outer Environment):全域性執行上下文沒有外部環境,它的外部環境為null。
全域性執行上下文是整個JavaScript程式的進口,它在程式執行期間始終存在,直到程式結束。所有的變數、函式都會成為全域性物件的屬性,可以透過全域性物件來訪問它們。因此,在編寫JavaScript程式時,需要留意全域性變數的使用,避免命名衝突和全域性變數汙染。
函式執行上下文
函式執行上下文是當JavaScript引擎執行一個函式時,建立的一個執行上下文。每個函式都會有自己的函式執行上下文。
函式執行上下文包含了以下幾個部門:
1.變數物件(Variable Object):函式執行上下文的變數物件包含了所有函式引數、內部變數、函式宣告等資訊。
2.作用域鏈(Scope Chain):作用域鏈由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。
3.this值:this指向呼叫該函式的物件。
當函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
function foo(a, b) {
var c = 1;
function bar() {
var d = 2;
console.log(a, b, c, d);
}
bar();
}
foo(10, 20);
當該程式碼執行時,JavaScript引擎會建立函式執行上下文,包括變數環境、詞法環境和this指向等資訊,並將其壓入執行上下文棧中。
具體來說,函式foo()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中a和b為引數,c為區域性變數,d為函式bar()內部的區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式foo()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:在該程式碼中,函式foo()會呼叫內部的函式bar()。
當函式bar()被呼叫時,JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中。
具體來說,函式bar()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中d為區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式bar()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:函式bar()沒有再次呼叫其他函式。
當函式bar()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時函式foo()的執行上下文仍在執行上下文棧的頂部。
函式foo()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧為空,JavaScript程式執行結束。
Eval函式執行上下文
Eval函式執行上下文是在呼叫eval函式時建立的執行上下文。Eval函式可以動態地執行JavaScript程式碼,並且可以訪問當前執行上下文的變數和函式。Eval函式執行上下文可以形成巢狀的作用域鏈,但它通常會被以為是當前執行上下文的一部分,而不是一個單獨的執行上下文。
Eval函式是JavaScript中的一個內建函式,用於執行動態建立的JavaScript程式碼。下面是一個簡樸的Eval函式案例:
let x = 1;
let y = 2;
let code = "console.log(x + y);"; // 動態建立的程式碼
eval(code); // 輸出結果為3
在上面的例子中,我們建立了一個字串變數code,該變數儲存了要執行的程式碼,即輸出x和y的和。然後,我們呼叫了eval函式,將字串code作為引數傳入。eval函式將字串作為JavaScript程式碼執行,輸出了3。
需要留意的是,eval函式的使用應該非常小心,由於它會執行傳入的任意程式碼,可能會導致意料之外的結果,並且可能會有安全隱患。建議在使用eval函式時,必需要確保傳入的程式碼是可託的,避免執行惡意程式碼。
總結
執行上下文是JavaScript中一個重要的概念,用於描述程式碼執行時的環境。一個執行上下文可以看作是一個獨立的環境,包含了當前程式碼執行所需的所有資訊,如變數、函式、this指向等。JavaScript中有三種類型的執行上下文:全域性執行上下文、函式執行上下文和eval函式執行上下文。
執行上下文分為兩個階段:建立階段和執行階段。在建立階段,JavaScript引擎會對程式碼進行解析,並將變數和函式宣告新增到當前執行上下文的作用域中。在執行階段,JavaScript引擎會逐行執行程式碼,並完成變數賦值、函式呼叫、this指向、閉包和垃圾回收等任務。
執行上下文(Execution Context)是JavaScript中一個非常重要的概念,它是程式碼執行時的環境資訊,包含了變數、函式、作用域等資訊。每當JavaScript引擎執行一段可執行程式碼時,都會建立一個執行上下文,該上下文會被壓入執行上下文棧中,當執行完畢後,該上下文將從棧中彈出。
一、執行上下文的階段
JavaScript程式的執行過程可以分為兩個階段,建立階段和執行階段。執行上下文的建立和執行也分別發生在這兩個階段中。
1.建立階段:在建立階段,JavaScript引擎會掃描整個程式碼,將變數宣告和函式宣告新增到變數物件中。此時,執行上下文的變數物件和作用域鏈已經建立,但是還未有詳細的值。
2.執行階段:在執行階段,JavaScript引擎會逐行執行程式碼,同時根據需要更新變數物件中的值,執行函式呼叫等操縱。在執行函式時,會建立函式執行上下文,並將其壓入執行上下文棧中。函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
可以看出,執行上下文的建立和執行發生在程式的不同階段,這也反映了JavaScript語言的特性:動態、解釋性、基於物件等。在編寫JavaScript程式時,需要了解執行上下文的概念和工作原理,以便更好地理解JavaScript的執行機制和除錯程式。

建立階段
執行上下文的建立階段是JavaScript引擎在執行JavaScript程式之前,對程式進行掃描和處理的階段。在建立階段,JavaScript引擎會完成以下幾個任務:
1.建立變數物件(Variable Object):JavaScript引擎會建立當前執行上下文的變數物件,用於儲存變數和函式宣告。對於全域性執行上下文來說,變數物件就是全域性物件(例如window物件);對於函式執行上下文來說,變數物件包括函式引數、內部變數和函式宣告等。
2.建立作用域鏈(Scope Chain):作用域鏈是由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。JavaScript引擎會在建立階段建立作用域鏈,以便在執行階段使用。
3.確定this指向:在建立階段,JavaScript引擎會確定當前執行上下文的this指向。對於全域性執行上下文來說,this指向全域性物件;對於函式執行上下文來說,this指向呼叫該函式的物件。
需要留意的是,在建立階段變數物件已經被建立,但變數的值還沒有被賦予,因此在建立階段訪問變數時,變數的值為undefined。在執行階段,當變數的值被賦予後,變數的值就會被更新。
執行階段
執行上下文的執行階段是JavaScript引擎在編譯階段之後,對JavaScript程式進行逐行執行的階段。在執行階段,JavaScript引擎會完成以下幾個任務:
1.變數賦值:在執行階段,JavaScript引擎會逐行執行程式碼,並對變數進行賦值。假如變數還沒有被宣告,JavaScript引擎會丟擲ReferenceError異常。
2.函式呼叫:假如程式碼中包含函式呼叫,JavaScript引擎會建立新的函式執行上下文,並將其壓入執行上下文棧中。在函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,繼續執行上一個執行上下文。
3.閉包:在執行階段,假如函式內部引用了外部變數,就會形成閉包。JavaScript引擎會將外部變數的值留存在閉包中,以便在函式執行期間訪問。
4.垃圾回收:在執行階段,JavaScript引擎會按期執行垃圾回收,以便清理不再使用的記憶體。需要留意的是,執行階段是一個逐行執行的過程,一旦泛起錯誤,JavaScript引擎就會當即住手執行,並丟擲異常。因此,在編寫JavaScript程式時,需要留意程式碼的正確性和可讀性,以便更好地除錯程式。
二、執行上下文棧
執行上下文棧是JavaScript中治理執行上下文的一種資料結構,它用於跟蹤程式碼的執行,並治理程式碼執行時所需的上下文環境。執行上下文棧是一個後進先出(LIFO)的資料結構,即最後一個進入的執行上下文會被最先執行和彈出。
當JavaScript程式開始執行時,會建立全域性執行上下文,並將其壓入執行上下文棧中。跟著程式碼的執行,每當碰到一個函式呼叫語句,JavaScript引擎就會建立一個新的函式執行上下文,並將其壓入執行上下文棧中。當函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,並繼續執行上一個執行上下文。
執行上下文棧的頂部始終是當前正在執行的程式碼所在的執行上下文。當執行上下文棧為空時,JavaScript程式執行結束。
var a = 1;
function foo() {
var b = 2;
function bar() {
var c = 3;
console.log(a, b, c);
}
bar();
}
foo();
當該程式碼執行時,JavaScript引擎會建立執行上下文棧,並按照以下順序進行壓棧和出棧操縱:
1.建立全域性執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中只有全域性執行上下文。
2.執行到函式foo(),JavaScript引擎會建立函式foo()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
3.執行到函式bar(),JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:bar()執行上下文 -> foo()執行上下文 -> 全域性執行上下文。
4.函式bar()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
5.函式foo()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:全域性執行上下文。
6.程式執行結束,JavaScript引擎結束執行。
透過執行上下文棧的治理,JavaScript引擎可以跟蹤程式碼的執行過程,並及時建立和銷燬執行上下文環境,確保程式碼的準確執行和記憶體治理。
三、執行上下文的分類
執行上下文可以分為以下三種類型:
1.全域性執行上下文(Global Execution Context)
2.函式執行上下文(Function Execution Context)
3.Eval函式執行上下文(Eval Function Execution Context)
需要留意的是,每個執行上下文都會被建立成一個獨立的環境,並且在執行完畢後會被銷燬。在執行上下文銷燬之前,JavaScript引擎會對其進行垃圾回收,以便開釋不再使用的記憶體。
全域性執行上下文
全域性執行上下文是JavaScript程式執行時的預設執行上下文,它是整個程式的頂層執行上下文。當JavaScript程式開始執行時,JavaScript引擎會自動建立並壓入全域性執行上下文到執行上下文棧中。
全域性執行上下文包含了以下幾個部門:
1.全域性物件(Global Object):它是全域性執行上下文的變數物件,包含了所有全域性變數、全域性函式等資訊。在瀏覽器環境中,全域性物件就是window物件。
2.this值:在全域性執行上下文中,this指向全域性物件。在瀏覽器環境中,this指向window物件。
3.外部環境(Outer Environment):全域性執行上下文沒有外部環境,它的外部環境為null。
全域性執行上下文是整個JavaScript程式的進口,它在程式執行期間始終存在,直到程式結束。所有的變數、函式都會成為全域性物件的屬性,可以透過全域性物件來訪問它們。因此,在編寫JavaScript程式時,需要留意全域性變數的使用,避免命名衝突和全域性變數汙染。
函式執行上下文
函式執行上下文是當JavaScript引擎執行一個函式時,建立的一個執行上下文。每個函式都會有自己的函式執行上下文。
函式執行上下文包含了以下幾個部門:
1.變數物件(Variable Object):函式執行上下文的變數物件包含了所有函式引數、內部變數、函式宣告等資訊。
2.作用域鏈(Scope Chain):作用域鏈由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。
3.this值:this指向呼叫該函式的物件。
當函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
function foo(a, b) {
var c = 1;
function bar() {
var d = 2;
console.log(a, b, c, d);
}
bar();
}
foo(10, 20);
當該程式碼執行時,JavaScript引擎會建立函式執行上下文,包括變數環境、詞法環境和this指向等資訊,並將其壓入執行上下文棧中。
具體來說,函式foo()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中a和b為引數,c為區域性變數,d為函式bar()內部的區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式foo()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:在該程式碼中,函式foo()會呼叫內部的函式bar()。
當函式bar()被呼叫時,JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中。
具體來說,函式bar()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中d為區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式bar()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:函式bar()沒有再次呼叫其他函式。
當函式bar()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時函式foo()的執行上下文仍在執行上下文棧的頂部。
函式foo()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧為空,JavaScript程式執行結束。
Eval函式執行上下文
Eval函式執行上下文是在呼叫eval函式時建立的執行上下文。Eval函式可以動態地執行JavaScript程式碼,並且可以訪問當前執行上下文的變數和函式。Eval函式執行上下文可以形成巢狀的作用域鏈,但它通常會被以為是當前執行上下文的一部分,而不是一個單獨的執行上下文。
Eval函式是JavaScript中的一個內建函式,用於執行動態建立的JavaScript程式碼。下面是一個簡樸的Eval函式案例:
let x = 1;
let y = 2;
let code = "console.log(x + y);"; // 動態建立的程式碼
eval(code); // 輸出結果為3
在上面的例子中,我們建立了一個字串變數code,該變數儲存了要執行的程式碼,即輸出x和y的和。然後,我們呼叫了eval函式,將字串code作為引數傳入。eval函式將字串作為JavaScript程式碼執行,輸出了3。
需要留意的是,eval函式的使用應該非常小心,由於它會執行傳入的任意程式碼,可能會導致意料之外的結果,並且可能會有安全隱患。建議在使用eval函式時,必需要確保傳入的程式碼是可託的,避免執行惡意程式碼。
總結
執行上下文是JavaScript中一個重要的概念,用於描述程式碼執行時的環境。一個執行上下文可以看作是一個獨立的環境,包含了當前程式碼執行所需的所有資訊,如變數、函式、this指向等。JavaScript中有三種類型的執行上下文:全域性執行上下文、函式執行上下文和eval函式執行上下文。
執行上下文分為兩個階段:建立階段和執行階段。在建立階段,JavaScript引擎會對程式碼進行解析,並將變數和函式宣告新增到當前執行上下文的作用域中。在執行階段,JavaScript引擎會逐行執行程式碼,並完成變數賦值、函式呼叫、this指向、閉包和垃圾回收等任務。
執行上下文(Execution Context)是JavaScript中一個非常重要的概念,它是程式碼執行時的環境資訊,包含了變數、函式、作用域等資訊。每當JavaScript引擎執行一段可執行程式碼時,都會建立一個執行上下文,該上下文會被壓入執行上下文棧中,當執行完畢後,該上下文將從棧中彈出。
一、執行上下文的階段
JavaScript程式的執行過程可以分為兩個階段,建立階段和執行階段。執行上下文的建立和執行也分別發生在這兩個階段中。
1.建立階段:在建立階段,JavaScript引擎會掃描整個程式碼,將變數宣告和函式宣告新增到變數物件中。此時,執行上下文的變數物件和作用域鏈已經建立,但是還未有詳細的值。
2.執行階段:在執行階段,JavaScript引擎會逐行執行程式碼,同時根據需要更新變數物件中的值,執行函式呼叫等操縱。在執行函式時,會建立函式執行上下文,並將其壓入執行上下文棧中。函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
可以看出,執行上下文的建立和執行發生在程式的不同階段,這也反映了JavaScript語言的特性:動態、解釋性、基於物件等。在編寫JavaScript程式時,需要了解執行上下文的概念和工作原理,以便更好地理解JavaScript的執行機制和除錯程式。

建立階段
執行上下文的建立階段是JavaScript引擎在執行JavaScript程式之前,對程式進行掃描和處理的階段。在建立階段,JavaScript引擎會完成以下幾個任務:
1.建立變數物件(Variable Object):JavaScript引擎會建立當前執行上下文的變數物件,用於儲存變數和函式宣告。對於全域性執行上下文來說,變數物件就是全域性物件(例如window物件);對於函式執行上下文來說,變數物件包括函式引數、內部變數和函式宣告等。
2.建立作用域鏈(Scope Chain):作用域鏈是由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。JavaScript引擎會在建立階段建立作用域鏈,以便在執行階段使用。
3.確定this指向:在建立階段,JavaScript引擎會確定當前執行上下文的this指向。對於全域性執行上下文來說,this指向全域性物件;對於函式執行上下文來說,this指向呼叫該函式的物件。
需要留意的是,在建立階段變數物件已經被建立,但變數的值還沒有被賦予,因此在建立階段訪問變數時,變數的值為undefined。在執行階段,當變數的值被賦予後,變數的值就會被更新。
執行階段
執行上下文的執行階段是JavaScript引擎在編譯階段之後,對JavaScript程式進行逐行執行的階段。在執行階段,JavaScript引擎會完成以下幾個任務:
1.變數賦值:在執行階段,JavaScript引擎會逐行執行程式碼,並對變數進行賦值。假如變數還沒有被宣告,JavaScript引擎會丟擲ReferenceError異常。
2.函式呼叫:假如程式碼中包含函式呼叫,JavaScript引擎會建立新的函式執行上下文,並將其壓入執行上下文棧中。在函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,繼續執行上一個執行上下文。
3.閉包:在執行階段,假如函式內部引用了外部變數,就會形成閉包。JavaScript引擎會將外部變數的值留存在閉包中,以便在函式執行期間訪問。
4.垃圾回收:在執行階段,JavaScript引擎會按期執行垃圾回收,以便清理不再使用的記憶體。需要留意的是,執行階段是一個逐行執行的過程,一旦泛起錯誤,JavaScript引擎就會當即住手執行,並丟擲異常。因此,在編寫JavaScript程式時,需要留意程式碼的正確性和可讀性,以便更好地除錯程式。
二、執行上下文棧
執行上下文棧是JavaScript中治理執行上下文的一種資料結構,它用於跟蹤程式碼的執行,並治理程式碼執行時所需的上下文環境。執行上下文棧是一個後進先出(LIFO)的資料結構,即最後一個進入的執行上下文會被最先執行和彈出。
當JavaScript程式開始執行時,會建立全域性執行上下文,並將其壓入執行上下文棧中。跟著程式碼的執行,每當碰到一個函式呼叫語句,JavaScript引擎就會建立一個新的函式執行上下文,並將其壓入執行上下文棧中。當函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,並繼續執行上一個執行上下文。
執行上下文棧的頂部始終是當前正在執行的程式碼所在的執行上下文。當執行上下文棧為空時,JavaScript程式執行結束。
var a = 1;
function foo() {
var b = 2;
function bar() {
var c = 3;
console.log(a, b, c);
}
bar();
}
foo();
當該程式碼執行時,JavaScript引擎會建立執行上下文棧,並按照以下順序進行壓棧和出棧操縱:
1.建立全域性執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中只有全域性執行上下文。
2.執行到函式foo(),JavaScript引擎會建立函式foo()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
3.執行到函式bar(),JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:bar()執行上下文 -> foo()執行上下文 -> 全域性執行上下文。
4.函式bar()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
5.函式foo()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:全域性執行上下文。
6.程式執行結束,JavaScript引擎結束執行。
透過執行上下文棧的治理,JavaScript引擎可以跟蹤程式碼的執行過程,並及時建立和銷燬執行上下文環境,確保程式碼的準確執行和記憶體治理。
三、執行上下文的分類
執行上下文可以分為以下三種類型:
1.全域性執行上下文(Global Execution Context)
2.函式執行上下文(Function Execution Context)
3.Eval函式執行上下文(Eval Function Execution Context)
需要留意的是,每個執行上下文都會被建立成一個獨立的環境,並且在執行完畢後會被銷燬。在執行上下文銷燬之前,JavaScript引擎會對其進行垃圾回收,以便開釋不再使用的記憶體。
全域性執行上下文
全域性執行上下文是JavaScript程式執行時的預設執行上下文,它是整個程式的頂層執行上下文。當JavaScript程式開始執行時,JavaScript引擎會自動建立並壓入全域性執行上下文到執行上下文棧中。
全域性執行上下文包含了以下幾個部門:
1.全域性物件(Global Object):它是全域性執行上下文的變數物件,包含了所有全域性變數、全域性函式等資訊。在瀏覽器環境中,全域性物件就是window物件。
2.this值:在全域性執行上下文中,this指向全域性物件。在瀏覽器環境中,this指向window物件。
3.外部環境(Outer Environment):全域性執行上下文沒有外部環境,它的外部環境為null。
全域性執行上下文是整個JavaScript程式的進口,它在程式執行期間始終存在,直到程式結束。所有的變數、函式都會成為全域性物件的屬性,可以透過全域性物件來訪問它們。因此,在編寫JavaScript程式時,需要留意全域性變數的使用,避免命名衝突和全域性變數汙染。
函式執行上下文
函式執行上下文是當JavaScript引擎執行一個函式時,建立的一個執行上下文。每個函式都會有自己的函式執行上下文。
函式執行上下文包含了以下幾個部門:
1.變數物件(Variable Object):函式執行上下文的變數物件包含了所有函式引數、內部變數、函式宣告等資訊。
2.作用域鏈(Scope Chain):作用域鏈由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。
3.this值:this指向呼叫該函式的物件。
當函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
function foo(a, b) {
var c = 1;
function bar() {
var d = 2;
console.log(a, b, c, d);
}
bar();
}
foo(10, 20);
當該程式碼執行時,JavaScript引擎會建立函式執行上下文,包括變數環境、詞法環境和this指向等資訊,並將其壓入執行上下文棧中。
具體來說,函式foo()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中a和b為引數,c為區域性變數,d為函式bar()內部的區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式foo()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:在該程式碼中,函式foo()會呼叫內部的函式bar()。
當函式bar()被呼叫時,JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中。
具體來說,函式bar()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中d為區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式bar()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:函式bar()沒有再次呼叫其他函式。
當函式bar()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時函式foo()的執行上下文仍在執行上下文棧的頂部。
函式foo()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧為空,JavaScript程式執行結束。
Eval函式執行上下文
Eval函式執行上下文是在呼叫eval函式時建立的執行上下文。Eval函式可以動態地執行JavaScript程式碼,並且可以訪問當前執行上下文的變數和函式。Eval函式執行上下文可以形成巢狀的作用域鏈,但它通常會被以為是當前執行上下文的一部分,而不是一個單獨的執行上下文。
Eval函式是JavaScript中的一個內建函式,用於執行動態建立的JavaScript程式碼。下面是一個簡樸的Eval函式案例:
let x = 1;
let y = 2;
let code = "console.log(x + y);"; // 動態建立的程式碼
eval(code); // 輸出結果為3
在上面的例子中,我們建立了一個字串變數code,該變數儲存了要執行的程式碼,即輸出x和y的和。然後,我們呼叫了eval函式,將字串code作為引數傳入。eval函式將字串作為JavaScript程式碼執行,輸出了3。
需要留意的是,eval函式的使用應該非常小心,由於它會執行傳入的任意程式碼,可能會導致意料之外的結果,並且可能會有安全隱患。建議在使用eval函式時,必需要確保傳入的程式碼是可託的,避免執行惡意程式碼。
總結
執行上下文是JavaScript中一個重要的概念,用於描述程式碼執行時的環境。一個執行上下文可以看作是一個獨立的環境,包含了當前程式碼執行所需的所有資訊,如變數、函式、this指向等。JavaScript中有三種類型的執行上下文:全域性執行上下文、函式執行上下文和eval函式執行上下文。
執行上下文分為兩個階段:建立階段和執行階段。在建立階段,JavaScript引擎會對程式碼進行解析,並將變數和函式宣告新增到當前執行上下文的作用域中。在執行階段,JavaScript引擎會逐行執行程式碼,並完成變數賦值、函式呼叫、this指向、閉包和垃圾回收等任務。
執行上下文(Execution Context)是JavaScript中一個非常重要的概念,它是程式碼執行時的環境資訊,包含了變數、函式、作用域等資訊。每當JavaScript引擎執行一段可執行程式碼時,都會建立一個執行上下文,該上下文會被壓入執行上下文棧中,當執行完畢後,該上下文將從棧中彈出。
一、執行上下文的階段
JavaScript程式的執行過程可以分為兩個階段,建立階段和執行階段。執行上下文的建立和執行也分別發生在這兩個階段中。
1.建立階段:在建立階段,JavaScript引擎會掃描整個程式碼,將變數宣告和函式宣告新增到變數物件中。此時,執行上下文的變數物件和作用域鏈已經建立,但是還未有詳細的值。
2.執行階段:在執行階段,JavaScript引擎會逐行執行程式碼,同時根據需要更新變數物件中的值,執行函式呼叫等操縱。在執行函式時,會建立函式執行上下文,並將其壓入執行上下文棧中。函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
可以看出,執行上下文的建立和執行發生在程式的不同階段,這也反映了JavaScript語言的特性:動態、解釋性、基於物件等。在編寫JavaScript程式時,需要了解執行上下文的概念和工作原理,以便更好地理解JavaScript的執行機制和除錯程式。

建立階段
執行上下文的建立階段是JavaScript引擎在執行JavaScript程式之前,對程式進行掃描和處理的階段。在建立階段,JavaScript引擎會完成以下幾個任務:
1.建立變數物件(Variable Object):JavaScript引擎會建立當前執行上下文的變數物件,用於儲存變數和函式宣告。對於全域性執行上下文來說,變數物件就是全域性物件(例如window物件);對於函式執行上下文來說,變數物件包括函式引數、內部變數和函式宣告等。
2.建立作用域鏈(Scope Chain):作用域鏈是由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。JavaScript引擎會在建立階段建立作用域鏈,以便在執行階段使用。
3.確定this指向:在建立階段,JavaScript引擎會確定當前執行上下文的this指向。對於全域性執行上下文來說,this指向全域性物件;對於函式執行上下文來說,this指向呼叫該函式的物件。
需要留意的是,在建立階段變數物件已經被建立,但變數的值還沒有被賦予,因此在建立階段訪問變數時,變數的值為undefined。在執行階段,當變數的值被賦予後,變數的值就會被更新。
執行階段
執行上下文的執行階段是JavaScript引擎在編譯階段之後,對JavaScript程式進行逐行執行的階段。在執行階段,JavaScript引擎會完成以下幾個任務:
1.變數賦值:在執行階段,JavaScript引擎會逐行執行程式碼,並對變數進行賦值。假如變數還沒有被宣告,JavaScript引擎會丟擲ReferenceError異常。
2.函式呼叫:假如程式碼中包含函式呼叫,JavaScript引擎會建立新的函式執行上下文,並將其壓入執行上下文棧中。在函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,繼續執行上一個執行上下文。
3.閉包:在執行階段,假如函式內部引用了外部變數,就會形成閉包。JavaScript引擎會將外部變數的值留存在閉包中,以便在函式執行期間訪問。
4.垃圾回收:在執行階段,JavaScript引擎會按期執行垃圾回收,以便清理不再使用的記憶體。需要留意的是,執行階段是一個逐行執行的過程,一旦泛起錯誤,JavaScript引擎就會當即住手執行,並丟擲異常。因此,在編寫JavaScript程式時,需要留意程式碼的正確性和可讀性,以便更好地除錯程式。
二、執行上下文棧
執行上下文棧是JavaScript中治理執行上下文的一種資料結構,它用於跟蹤程式碼的執行,並治理程式碼執行時所需的上下文環境。執行上下文棧是一個後進先出(LIFO)的資料結構,即最後一個進入的執行上下文會被最先執行和彈出。
當JavaScript程式開始執行時,會建立全域性執行上下文,並將其壓入執行上下文棧中。跟著程式碼的執行,每當碰到一個函式呼叫語句,JavaScript引擎就會建立一個新的函式執行上下文,並將其壓入執行上下文棧中。當函式執行完畢後,JavaScript引擎會從執行上下文棧中彈出該函式執行上下文,並繼續執行上一個執行上下文。
執行上下文棧的頂部始終是當前正在執行的程式碼所在的執行上下文。當執行上下文棧為空時,JavaScript程式執行結束。
var a = 1;
function foo() {
var b = 2;
function bar() {
var c = 3;
console.log(a, b, c);
}
bar();
}
foo();
當該程式碼執行時,JavaScript引擎會建立執行上下文棧,並按照以下順序進行壓棧和出棧操縱:
1.建立全域性執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中只有全域性執行上下文。
2.執行到函式foo(),JavaScript引擎會建立函式foo()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
3.執行到函式bar(),JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中,此時執行上下文棧中的順序為:bar()執行上下文 -> foo()執行上下文 -> 全域性執行上下文。
4.函式bar()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:foo()執行上下文 -> 全域性執行上下文。
5.函式foo()執行完畢,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧中的順序為:全域性執行上下文。
6.程式執行結束,JavaScript引擎結束執行。
透過執行上下文棧的治理,JavaScript引擎可以跟蹤程式碼的執行過程,並及時建立和銷燬執行上下文環境,確保程式碼的準確執行和記憶體治理。
三、執行上下文的分類
執行上下文可以分為以下三種類型:
1.全域性執行上下文(Global Execution Context)
2.函式執行上下文(Function Execution Context)
3.Eval函式執行上下文(Eval Function Execution Context)
需要留意的是,每個執行上下文都會被建立成一個獨立的環境,並且在執行完畢後會被銷燬。在執行上下文銷燬之前,JavaScript引擎會對其進行垃圾回收,以便開釋不再使用的記憶體。
全域性執行上下文
全域性執行上下文是JavaScript程式執行時的預設執行上下文,它是整個程式的頂層執行上下文。當JavaScript程式開始執行時,JavaScript引擎會自動建立並壓入全域性執行上下文到執行上下文棧中。
全域性執行上下文包含了以下幾個部門:
1.全域性物件(Global Object):它是全域性執行上下文的變數物件,包含了所有全域性變數、全域性函式等資訊。在瀏覽器環境中,全域性物件就是window物件。
2.this值:在全域性執行上下文中,this指向全域性物件。在瀏覽器環境中,this指向window物件。
3.外部環境(Outer Environment):全域性執行上下文沒有外部環境,它的外部環境為null。
全域性執行上下文是整個JavaScript程式的進口,它在程式執行期間始終存在,直到程式結束。所有的變數、函式都會成為全域性物件的屬性,可以透過全域性物件來訪問它們。因此,在編寫JavaScript程式時,需要留意全域性變數的使用,避免命名衝突和全域性變數汙染。
函式執行上下文
函式執行上下文是當JavaScript引擎執行一個函式時,建立的一個執行上下文。每個函式都會有自己的函式執行上下文。
函式執行上下文包含了以下幾個部門:
1.變數物件(Variable Object):函式執行上下文的變數物件包含了所有函式引數、內部變數、函式宣告等資訊。
2.作用域鏈(Scope Chain):作用域鏈由當前執行上下文的變數物件和其外部環境的變數物件鏈組成,用於解析變數的位置。
3.this值:this指向呼叫該函式的物件。
當函式執行完畢後,函式執行上下文會從執行上下文棧中彈出,程式繼續執行上一個執行上下文。
function foo(a, b) {
var c = 1;
function bar() {
var d = 2;
console.log(a, b, c, d);
}
bar();
}
foo(10, 20);
當該程式碼執行時,JavaScript引擎會建立函式執行上下文,包括變數環境、詞法環境和this指向等資訊,並將其壓入執行上下文棧中。
具體來說,函式foo()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中a和b為引數,c為區域性變數,d為函式bar()內部的區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式foo()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:在該程式碼中,函式foo()會呼叫內部的函式bar()。
當函式bar()被呼叫時,JavaScript引擎會建立函式bar()的執行上下文,並將其壓入執行上下文棧中。
具體來說,函式bar()的執行上下文包括:
1.變數環境:包括函式引數和在函式內部宣告的變數,其中d為區域性變數。
2.詞法環境:與變數環境類似,包括函式引數和在函式內部宣告的變數,但不包括函式內部巢狀的函式中的變數。
3.this指向:在該程式碼中,函式bar()是作為普通函式呼叫的,因此this指向全域性物件(瀏覽器環境下為window物件)。
函式呼叫:函式bar()沒有再次呼叫其他函式。
當函式bar()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時函式foo()的執行上下文仍在執行上下文棧的頂部。
函式foo()執行完畢後,JavaScript引擎會將其執行上下文彈出執行上下文棧,此時執行上下文棧為空,JavaScript程式執行結束。
Eval函式執行上下文
Eval函式執行上下文是在呼叫eval函式時建立的執行上下文。Eval函式可以動態地執行JavaScript程式碼,並且可以訪問當前執行上下文的變數和函式。Eval函式執行上下文可以形成巢狀的作用域鏈,但它通常會被以為是當前執行上下文的一部分,而不是一個單獨的執行上下文。
Eval函式是JavaScript中的一個內建函式,用於執行動態建立的JavaScript程式碼。下面是一個簡樸的Eval函式案例:
let x = 1;
let y = 2;
let code = "console.log(x + y);"; // 動態建立的程式碼
eval(code); // 輸出結果為3
在上面的例子中,我們建立了一個字串變數code,該變數儲存了要執行的程式碼,即輸出x和y的和。然後,我們呼叫了eval函式,將字串code作為引數傳入。eval函式將字串作為JavaScript程式碼執行,輸出了3。
需要留意的是,eval函式的使用應該非常小心,由於它會執行傳入的任意程式碼,可能會導致意料之外的結果,並且可能會有安全隱患。建議在使用eval函式時,必需要確保傳入的程式碼是可託的,避免執行惡意程式碼。
總結
執行上下文是JavaScript中一個重要的概念,用於描述程式碼執行時的環境。一個執行上下文可以看作是一個獨立的環境,包含了當前程式碼執行所需的所有資訊,如變數、函式、this指向等。JavaScript中有三種類型的執行上下文:全域性執行上下文、函式執行上下文和eval函式執行上下文。
執行上下文分為兩個階段:建立階段和執行階段。在建立階段,JavaScript引擎會對程式碼進行解析,並將變數和函式宣告新增到當前執行上下文的作用域中。在執行階段,JavaScript引擎會逐行執行程式碼,並完成變數賦值、函式呼叫、this指向、閉包和垃圾回收等任務。