JavaScript之執行順序

前言

接觸js一段時間以來,覺得隻是瞭解瞭很淺層的東西。對於很多基礎的知識還是很欠缺的。所以開始使用博客來對這一部分的知識做個慢慢的記錄和積累。相信積少成多,慢慢的將這一部分的知識攻克!

第一篇記錄的不是相關的應用,而是很底層的知識—JavaScript解析引擎。想要瞭解這一部分的知識也是通過在項目中遇到的問題而聯想到的。

問題的背景

在一段腳本中,執行的順序是先將js文件中的alert()執行瞭一遍,然後當我具體調用到那個函數的時候再執行這個函數。當時看到就產生瞭一個疑問:執行函數之前為什麼執行瞭alert(),很明顯他沒有執行我定義的函數,卻執行瞭alert();


js執行測試

<script>
	var a ;
	a = 1;
	function f1(){ alert("第一個函數"); }
	alert("測試");
	function f2(){ alert("第二個函數"); }
	alert(a);
	function f3(){ alert("第三個函數"); }
</script>


	

測試

執行結果是:測試 1

需要瞭解的前提

需要瞭解兩個概念,一個是JavaScript解析引擎;另外一個是JavaScript解析引擎和瀏覽器的關系

1.JavaScript解析引擎

解釋執行腳本的程序。可以看成是一個解釋器。
這個引擎需要完成兩個功能:
一是解釋腳本程序,將js代碼讀懂。
二是執行腳本程序,將腳本程序讀懂之後就要執行這個程序。
比如在一篇博客中看到的一個例子,當你寫瞭 var a = 1 + 1; 這樣一段代碼,JavaScript引擎做的事情就是看懂(解析)你這段代碼,並且將a的值變為2。
看這個概念的時候還想起另外一個概念就是編譯器,它隻是將源代碼編譯成另外一種代碼(比如機器碼,或者字節碼)。就好象是一個翻譯官,將中文翻譯成英文。它不能夠執行這段程序。

2.JavaScript解析引擎和瀏覽器的關系

JavaScript解析引擎是瀏覽器的組成部分之一。
當瞭解瞭前提之後我們知道,我們寫的js代碼是需要通過瀏覽器中的JavaScript解析引擎解析執行的,具體的解析機制大傢可以google一下,我對這部分瞭解不深,隻知道瞭解各大概,但是我覺得這些知識對於我瞭解其他的知識已經足夠瞭。
解析機制分為兩個大過程,一個編譯過程,另外一個是執行過程。編譯過程最終是在內存中構建一個語法樹。執行過程就是按照語法樹來執行代碼。對於編譯和執行內部具體的運行我就不清楚瞭。

js代碼在頁面中的執行順序

上面講到的都是一些理論知識,下面就來看看我們在實際應用過程中會js代碼在頁面中的執行順序。這些就是上面理論知識的一些很形象的反應。

1. 引擎對js解析—預編譯和執行順序關系

它會在預編譯期對所有聲明的變量和函數進行處理。所以,就會出現當JavaScript解釋器執行下面腳本時不會報錯:


js執行測試

<script>
	alert(a);   //undefined
	var a ;
	a = 1;
	function f1(){ alert("第一個函數"); }
	alert("測試");  //測試
	function f2(){ alert("第二個函數"); }
	alert(a);  //1
	function f3(){ alert("第三個函數"); }
</script>


	

測試

執行結果是: undefined 測試 1

預編譯做的工作:將聲明的變量和函數做處理,從而使其在執行期間對所有的代碼都是可見的。

但是,你也會看到,執行上面代碼,提示的值是 undefined,而不是1。這是因為,變量初始化過程發生在執行期,而不是預編譯期。在執行期,JavaScript解釋器是按著代碼先後順序進行解 析的,如果在前面代碼行中沒有為變量賦值,則JavaScript解釋器會使用默認值undefined。由於在第二行中為變量a賦值瞭,所以在第三行代 碼中會提示變量a的值為1,而不是undefined。

2. 文件流加載時—js按照HTML文檔流順序執行

js可以看成HTML文檔的組成部分。HTML文檔是從上到下逐步解析的。無論是使用<script></script>塊還是使用外部引用的js文件都是如此。

使用外部js文件引用,將上面的代碼寫到js文件中,執行結果不變


js執行測試

<script type="text/javascript" src="Untitled-2.js"></script>

	

測試

js文件

var a ;
a = 1;
function f1(){ alert("第一個函數"); }
alert("測試");
function f2(){ alert("第二個函數"); }
alert(a);
function f3(){ alert("第三個函數"); }

執行結果:測試 1

3. 文件流加載完成之後—按照事件機制改變js執行順序

類似於調用函數,在哪裡調用到就在此處執行,如果沒有調用到就不執行。從上面的代碼中可以看到,為a標簽添加瞭點擊事件,所以當單擊的時候會執行對應的函數

總結

所以可以解釋為什麼alert()執行瞭,而函數沒有執行。js解析引擎要有一個預編譯過程,對定義的變量和函數做處理。同時js還要根據HTML文檔流的順序執行。這就是執行我自己定義的函數之前的過程,而我所以的執行自己定義的函數其實是事件機制調用js的一個體現。

發佈留言