1. 程式人生 > >JS之執行上下文與執行上下文棧

JS之執行上下文與執行上下文棧

分享一下JS中很基礎也很重要的概念:執行上下文(Execution Context);

將我們的程式碼進行分類:

1.程式碼分類(位置):
          * 全域性程式碼
          * 函式(函式)程式碼.

2.全域性執行上下文
          (1) 在執行全域性程式碼前將window確定為全域性執行上下文
          (2)對全域性資料進行預處理
            * var定義的全域性變數===>undefined,新增為window的屬性
            * function宣告的全域性函式===>賦值(fun),新增為window的方法
            * this===>賦值(window) 
          (3) 開始執行全域性程式碼

3.函式執行上下文
          (1) 在呼叫函式,準備執行函式體之前,建立對應的函式執行上下文物件 
          (2) 對區域性資料進行預處理
            * 形參變數==>賦值(實參),新增為執行上下文的屬性 
            * arguments==>賦值(實參列表),新增為執行上下文的屬性
            * var定義的區域性變數==>undefined,新增為執行上下文的屬性
            * function宣告的函式==>賦值(fun),新增為執行上下文的屬性
            * this==>賦值(呼叫函式的物件)
          (3) 開始執行函式體程式碼

// 全域性執行上下文
	console.log(a1) // undefined
	console.log(a2) // 可以訪問到
	var a1 = 3
	function a2(){}


	// 函式執行上下文
	function fn(b1){
		console.log(b1) // 2
		console.log(b2) // undefined
		console.log(b3)
		b3()
		console.log(this) // window
		console.log(arguments) //[2,3]偽陣列


		var b2 = 3
		function b3(){
			console.log('b3')
		}


	}
	fn(2,3)

JS中並沒有嚴格意義上區分棧記憶體和堆記憶體,因此我們可以簡單粗暴的理解為JavaScript的所有資料都儲存在堆記憶體中。但是在某些場景,我們仍然需要基於堆疊資料結構的思維來實現一些功能,比如JavaScript的執行上下文.執行上下文的執行順序借用了棧資料結構的存取方式。(也就是我們說的函式呼叫棧).

棧的存取方式是先進後出.

當代碼的執行過程中,遇到全域性程式碼和函式程式碼都會生成一個執行上下文放入棧中,而處於棧頂的上下文執行完畢之後,就會自動出棧。

執行上下文棧:

1.在全域性程式碼執行前,JS就會建立一個棧來儲存管理所有的執行上下文物件
2.在全域性執行上下文(window)確定後,將其新增到棧中(壓棧)
3.在函式執行上下文建立後,將其新增到棧中(壓棧)
4.噹噹前函式執行完後,將棧頂的物件移除(出棧)
5.當所有的程式碼執行完後,棧中只剩window(全域性上下文)
    注意: 1.全域性上下文在瀏覽器視窗關閉後出棧
              2.函式執行中,遇到return直接終止可執行的程式碼,會直接將當前上下文彈出棧

function f1(){
	    var n=999;
	    function f2(){
	        console.log(n);
	    }
	    return f2;
	}
	var result=f1();
	result(); // 999
	console.log(result)

我們分析一下這段程式碼中執行上下文的順序:

第一步,首先是全域性上下文入棧

全域性上下文入棧之後,其中的可執行程式碼開始執行,直到遇到了f1();這一句啟用函式f1建立它自己的執行上下文,因此第二步就是f1的執行上下文入棧。

f1中的可執行程式碼並沒有呼叫f2,所以沒有建立新的上下文,直到return f2時才建立.這時候f1可執行程式碼完畢,出棧

遇到result(),建立result的執行上下文

執行result中的可執行程式碼,輸出n,執行完畢後,result出棧

這個時候只剩下全域性上下文,全域性上下文在瀏覽器視窗關閉後出棧.

對執行上下文總結一下:

  • 執行上下文是單執行緒的
  • 是同步執行,只有棧頂的上下文處於執行中,其他上下文需要等待
  • 全域性上下文只有唯一的一個,它在瀏覽器關閉時出棧
  • 函式的執行上下文的個數沒有限制
  • 每次某個函式被呼叫,就會有個新的執行上下文為其建立,即使是呼叫的自身函式,也是如此。