JavaScript執行上下文,執行上下文棧

背景:在面試中經常會遇到函數和變量提升,作用域等問題,如果想深入理解其原理,那麼首先要弄清楚函數執行上下文和執行上下文棧這兩個概念。

再次之前先介紹下棧的數據結構:


總結起來一句話:新的數據從棧頂壓入,彈出數據也是從棧頂進行彈出,也就是我們所說的彈夾原理。

1.執行上下文(Excution Context)

執行上下文可以理解爲當前代碼的執行環境,它會形成一個作用域。JavaScript中的運行環境大概包括三種情況。

全局環境:JavaScript代碼運行起來會首先進入該環境

函數環境:當函數被調用執行時,會進入當前函數中執行代碼

eval(不建議使用,可忽略)

2.執行環境棧(執行上下文棧Excution Context Stack)

JavaScript執行在單線程上,所以的代碼都是排隊執行.棧底永遠都是全局上下文,而棧頂就是當前正在執行的上下文。當一開始瀏覽

器執行全局的代碼時,首先創建唯一的一個全局的執行上下文,並將其壓入執行棧的頂部(在瀏覽器關閉的時候出棧).當沒進入一個函數

的執行就會創建新的函數執行上下文,並相應的壓入執行棧的頂部.當前函數完成之後,當前函數的執行上下文從棧頂出棧,等待垃圾回

收。

3.執行上下文的生命週期



總的生命週期:創建-->執行-->出棧等待銷燬

創建階段:
A 創建變量對象:首先初始化函數的參數arguments,初始化函數聲明,初始化變量(undefined)。函數的優先級要高於變量,如果變
量和函數名重名,變量會被忽略。
a 創建arguments對象,檢查上下文,初始化參數名稱和值並創建引用的複製。
b 掃描上下文的函數聲明(而非函數表達式)
1.每找到一個函數,在變量對象variableObject上創建一個屬性-----切確的說是函數的名字---屬性值就是指向該函數在內存中的地址的一個引用。
2.如果上述函數名已經存在於variableObject下,那麼對應的屬性值會被新的引用所覆蓋。
 掃描上下文的變量聲明
1.每找到一個變量聲明,就會在變量對象上創建一個屬性---就是變量名字,並且將變量的值初始化爲undefined
d.確定上下文內部this的指向
B 創建作用域鏈

執行階段:

         執行變量賦值,代碼執行

回收階段:

         執行上下文棧等待垃圾回收機制回收上下文

案例:(下面代碼用來說明執行上下文棧的工作原理)
	//變量聲明
	var a1 = 9,
	a2 = 8,
	a3 = "sss",
	b1 = {name:"xixi"};

	//函數調用
	a1 = f1(a1,a2);
	
	//函數聲明
	function f1(a,b){
		//f1函數的執行上下文
		/*
			1.掃描參數: a = 9 b = 8
			2.掃描函數聲明 f2 = function(){}
			3.掃描變量聲明 t = undefined , m = undefined , i = undefined
		*/
		var t = 0,
		m = 10;

		for(var i=0;i<a;i++){
			console.log(i);
		}

		function f2(){
			console.log("f2");
		}

		return a+b;
	}

環境棧示意圖:


以上是關於執行上下文執行環境棧的說明,關於作用域的問題可以參考本博客高級JavaScript部分的文章。
發佈了71 篇原創文章 · 獲贊 72 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章