JavaScript 預編譯原理及經典面試題

JS 語言的特點


在深入瞭解 JavaScript 的預編譯之前,不得不先來回憶一下 JS 語言的特點:

  1. 解釋型語言: 區別於編譯型語言,逐行編譯,就是編譯一行,執行一行,而且對速度要求並不是太高;
  2. JS 引擎是單線程的;
  3. JS 符合 ECMA 標準;
  4. JS 執行隊列類似於輪轉時間片。

JS 運行三部曲


在這裏,最重要的就是第一點:解釋型語言的運行過程。 JS 運行有三部曲:

  1. 語法分析:很簡單,就是通篇掃描一下有沒有低級語法(語義)錯誤;
  2. 預編譯: 簡單地說就是在內存中開闢了一些空間,存放一些變量與函數;
  3. 解釋執行:解釋一行,執行一行。

JS 預編譯實例


下面正式進入預編譯的介紹,看例子爲什麼控制檯可以打印出 ‘a’

	<script type="text/javascript">
		test();
		function test() {
			console.log('a');
		}
	</script>

如上邊示例,因爲有預編譯的存在,test() 的調用雖然在聲明之前,函數也可以執行。這是爲什麼呢?引出 預編譯前奏 這個概念:

預編譯前奏:

  1. imply global 暗示全局變量:即任何變量,如果變量未經聲明就賦值,此變量就爲全局對象所有;
eg: a = 123;
eg: var a = b = 123;
  1. 一切聲明的全局變量,全是 window 的屬性。
eg: var a = 123;

下圖爲一個實例,變量 a 雖然聲明瞭,但不是全局變量,所以不能在函數體外訪問到,但是變量 b 滿足預編譯前奏的第一點,未經聲明就被賦值,此變量爲全局對象所有,所以可以訪問到。
在這裏插入圖片描述
知道了預編譯前奏的概念,那麼我們的理解就已經深入了一半了,順着脈絡繼續。預編譯前奏生成 GO(Global Object)對象,之後如果有函數就進行預編譯,預編譯四部曲如下:

預編譯四部曲:

  1. 創建 AO 對象(Activation Object 俗稱執行期上下文);
  2. 找形參和變量聲明,將變量和形參名作爲 AO 屬性名,值爲 undefined;
  3. 將實參值和形參統一;
  4. 在函數體裏面找函數聲明,值賦予函數體。

通過簡單的實例來認識一下 GO 與 AO 的結合:預編譯前奏時,生成 window.b = 10;①預編譯時創建 AO 對象;②將變量聲明 a 放入 AO,值爲 undefined;③傳入參數,使得實參形參相統一,本例中沒有形參;④如果函數體裏還有函數聲明,值賦予函數體,但是本例中沒有。
最終,函數會打印出 undefined 。
在這裏插入圖片描述
再來一個例子,跟着我們前邊的節奏來分析,先寫下 GO 對象,再找 AO 對象。

	<script type="text/javascript">

		global = 100;
		function fn() {
			console.log(global);
			global = 200;
			console.log(global);
			var global = 300;
		}
		fn();
		var global;

	</script>

大家先來分析一下分別會輸出什麼呢?

在這裏插入圖片描述
我們來分析一下,global 未經聲明就賦值,生成 GO 對象 global = 100;在執行到 fn() 的前一刻進行預編譯,生成 AO 對象,其中只有 global,值爲undefined,之後既沒有實參的傳入,也沒有函數聲明,那麼第15行就打印 undefined了,經過16行之後,undefined 被修改爲200 。所以兩個答案分別是 undefined 和 200,你答對了嗎?

百度2013面試題:

題目一:
在這裏插入圖片描述
因爲在函數 bar 最頂端返回 foo,直接看到 AO 的第四部:返回函數聲明,那麼程序會打印函數 bar()。

題目二:
在這裏插入圖片描述
這題和上一個類似,因爲函數的最後返回 foo,而 foo 在上邊被賦值過,那麼 foo 一定爲該值咯。
看完之後我們發現,其實預編譯也並不難,再梳理一下:

總結


預編譯前奏:生成 GO 對象,有兩個規則;
預編譯四部曲:
1.創建 AO 對象
2. 找形參和變量聲明,將變量和形參名作爲 AO 屬性名,值爲 undefined;
3. 將實參值和形參統一;
4. 在函數體裏面找函數聲明,值賦予函數體。

底層基礎決定上層建築,這是不變的真理,深究原理絕對是沒錯的!

說在最後的話:編寫實屬不易,若喜歡或者對你有幫助記得點贊+關注或者收藏哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章