轉自:http://www.2cto.com/kf/201401/273825.html
JavaScript是一種描述型腳本語言,它不同於java或C#等編譯性語言,它不需要進行編譯成中間語言,而是由瀏覽器進行動態地解析與執行。如果你不能理解javaScript語言的運行機制,或者簡單地說,你不能掌握javascript的執行順序,那你就猶如伯樂駕馭不了千里馬,讓千里馬脫繮而出,四處亂竄。
那麼JavaScript是怎麼來進行解析的嗎?它的執行順序又是如何的呢?在瞭解這些之前,我們先來認識幾個重要的術語:
1、代碼塊
JavaScript中的代碼塊是指由<script>標籤分割的代碼段。例如:
1
2
3
4
5
6
|
<script
type= "text/javascript" > alert( "這是代碼塊一" ); </script> <script
type= "text/javascript" > alert( "這是代碼塊二" ); </script> |
JS是按照代碼塊來進行編譯和執行的,代碼塊間相互獨立,但變量和方法共享。什麼意思呢? 舉個例子,你就明白了:
1
2
3
4
5
6
7
8
9
|
<script
type= "text/javascript" > alert(str); //因爲沒有定義str,所以瀏覽器會出錯,下面的不能運行 alert( "我是代碼塊一" ); //沒有運行到這裏 var
test = "我是代碼塊一變量" ; </script> <script
type= "text/javascript" > alert( "我是代碼塊二" );
//這裏有運行到 alert(test);
//彈出"我是代碼塊一變量" </script> |
2、聲明式函數與賦值式函數
JS中的函數定義分爲兩種:聲明式函數與賦值式函數。
1
2
3
4
5
6
7
8
9
|
<script
type= "text/javascript" > function
Fn(){ //聲明式函數 } var
Fn = function{ //賦值式函數 } </script> |
3、預編譯期與執行期
事實上,JS的解析過程分爲兩個階段:預編譯期(預處理)與執行期。
預編譯期JS會對本代碼塊中的所有聲明的變量和函數進行處理(類似與C語言的編譯),但需要注意的是此時處理函數的只是聲明式函數,而且變量也只是進行了聲明但未進行初始化以及賦值。
1
2
3
4
5
6
7
8
9
10
|
<script
type= "text/javascript" > Fn();
//執行結果:"執行了函數2",同名函數後者會覆蓋前者 function
Fn(){ //函數1 alert( "執行了函數1" ); } function
Fn(){ //函數2 alert( "執行了函數2" ); } </script> |
1
2
3
4
5
6
7
8
9
10
|
<script
type= "text/javascript" > Fn();
//執行結果:"執行了聲明式函數",在預編譯期聲明函數及被處理了,所以即使Fn()調用函數放在聲明函數前也能執行。 function
Fn(){ //聲明式函數 alert( "執行了聲明式函數" ); } var
Fn = function(){ //賦值式函數 alert( "執行了賦值式函數" ); } </script> |
1
2
3
4
5
6
7
8
9
10
|
//代碼塊一 <script
type= "text/javascript" > alert(str); //瀏覽器報錯,但並沒有彈出信息窗 </script> //代碼塊二 <script
type= "text/javascript" > alert(str);
//彈窗"undefined" var
str = "aaa" ; </script> //js在預處理期對變量進行了聲明處理,但是並沒有進行初始化與賦值,所以導致代碼塊二中的變量是unfiened的,而代碼一中的變量是完全不存在的,所以瀏覽器報錯。 |
1
2
3
4
5
6
7
8
|
<script
type= "text/javascript" > Fn();
//瀏覽器報錯:"undefined" </script> <script
type= "text/javascript" > function
Fn(){ //函數1 alert( "執行了函數1" ); } </script> |
現在,讓我們來總結整理下:
step 1. 讀入第一個代碼塊。
step 2. 做語法分析,有錯則報語法錯誤(比如括號不匹配等),並跳轉到step5。
step 3. 對var變量和function定義做“預編譯處理”(永遠不會報錯的,因爲只解析正確的聲明)。
step 4. 執行代碼段,有錯則報錯(比如變量未定義)。
step 5. 如果還有下一個代碼段,則讀入下一個代碼段,重複step2。
step6. 結束。
而根據HTML文檔流的執行順序,需要在頁面元素渲染前執行的js代碼應該放在前面的<script>代碼塊中,而需要在頁面元素加載完後的js放在元素後面,body標籤的onload事件是在最後執行的。
1
2
3
4
5
6
7
8
9
10
11
12
|
<script
type= "text/javascript" > alert( "first" ); function
Fn(){ alert( "third" ); } </script> <script
type= "text/javascript" > alert( "second" ); </script>
|