DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JavaScript基礎知識 >> 深入理解javascript的執行順序
深入理解javascript的執行順序
編輯:JavaScript基礎知識     

如果你不能理解javaScript語言的運行機制,或者簡單地說,你不能掌握javascript的執行順序,那你就猶如伯樂駕馭不了千裡馬,讓千裡馬脫缰而出,四處亂竄。

那麼JavaScript是怎麼來進行解析的嗎?它的執行順序又是如何的呢?在了解這些之前,我們先來認識幾個重要的術語:

1、代碼塊
JavaScript中的代碼塊是指由<script>標簽分割的代碼段。例如:
復制代碼 代碼如下:
<script type="text/javascript">
      alert("這是代碼塊一");
</script>
<script type="text/javascript">
      alert("這是代碼塊二");
</script>

JS是按照代碼塊來進行編譯和執行的,代碼塊間相互獨立,但變量和方法共享。什麼意思呢? 舉個例子,你就明白了:
復制代碼 代碼如下:
<script type="text/javascript">
      alert(str);//因為沒有定義str,所以浏覽器會出錯,下面的不能運行
      alert("我是代碼塊一");//沒有運行到這裡
      var test = "我是代碼塊一變量";
</script>
<script type="text/javascript">
      alert("我是代碼塊二"); //這裡有運行到
      alert(test); //彈出"我是代碼塊一變量"
</script>
上面的代碼中代碼塊一中運行報錯,但不影響代碼塊二的執行,這就是代碼塊間的獨立性,而代碼塊二中能調用到代碼一中的變量,則是塊間共享性。

2、聲明式函數與賦值式函數


JS中的函數定義分為兩種:聲明式函數與賦值式函數。
復制代碼 代碼如下:
<script type="text/javascript">
     function Fn(){ //聲明式函數

     }

     var Fn = function{  //賦值式函數

     }
</script>
聲明式函數與賦值式函數的區別在於:在JS的預編譯期,聲明式函數將會先被提取出來,然後才按順序執行js代碼。

3、預編譯期與執行期


事實上,JS的解析過程分為兩個階段:預編譯期(預處理)與執行期。

預編譯期JS會對本代碼塊中的所有聲明的變量和函數進行處理(類似與C語言的編譯),但需要注意的是此時處理函數的只是聲明式函數,而且變量也只是進行了聲明但未進行初始化以及賦值。
復制代碼 代碼如下:
<script type="text/javascript">
     Fn();  //執行結果:"執行了函數2",同名函數後者會覆蓋前者
     function Fn(){ //函數1
        alert("執行了函數1");
     }

     function Fn(){  //函數2
        alert("執行了函數2");
     }
</script> 
<script type="text/javascript">
      Fn();  //執行結果:"執行了聲明式函數",在預編譯期聲明函數及被處理了,所以即使Fn()調用函數放在聲明函數前也能執行。
      function Fn(){ //聲明式函數
         alert("執行了聲明式函數");
      }

      var Fn = function(){  //賦值式函數
         alert("執行了賦值式函數");
      }
</script>

//代碼塊一
<script type="text/javascript">
      alert(str);//浏覽器報錯,但並沒有彈出信息窗
</script>
//代碼塊二
<script type="text/javascript">
      alert(str); //彈窗"undefined"
      var str = "aaa";
</script>
//js在預處理期對變量進行了聲明處理,但是並沒有進行初始化與賦值,所以導致代碼塊二中的變量是unfiened的,而代碼一中的變量是完全不存在的,所以浏覽器報錯。

理解了上面的幾個術語,相信大家對JS的運行機制已經有了個大概的印象了,現在我們來看個例子:
復制代碼 代碼如下:
<script type="text/javascript">
      Fn();  //浏覽器報錯:"undefined"
</script>
<script type="text/javascript">
      function Fn(){ //函數1
          alert("執行了函數1");
      }
</script>

為什麼運行上面的代碼浏覽器會報錯呢?聲明函數不是會在預處理期就會被處理了嗎,怎麼還會找不到Fn()函數呢?其實這是一個理解誤點,我們上面說了JS引擎是按照代碼塊來順序執行的,其實完整的說應該是按照代碼塊來進行預處理和執行的,也就是說預處理的只是執行到的代碼塊的聲明函數和變量,而對於還未加載的代碼塊,是沒法進行預處理的,這也是邊編譯邊處理的核心所在。

現在,讓我們來總結整理下:
復制代碼 代碼如下:
  step 1.  讀入第一個代碼塊。
  step 2.  做語法分析,有錯則報語法錯誤(比如括號不匹配等),並跳轉到step5。
  step 3.  對var變量和function定義做“預編譯處理”(永遠不會報錯的,因為只解析正確的聲明)。
  step 4.  執行代碼段,有錯則報錯(比如變量未定義)。
  step 5.  如果還有下一個代碼段,則讀入下一個代碼段,重復step2。
  step6. 結束。

而根據HTML文檔流的執行順序,需要在頁面元素渲染前執行的js代碼應該放在<body>前面的<script>代碼塊中,而需要在頁面元素加載完後的js放在</body>元素後面,body標簽的onload事件是在最後執行的。
復制代碼 代碼如下:
<script type="text/javascript">
    alert("first");
    function Fn(){
     alert("third");
    }
</script>
<body onload="Fn()">

</body>
<script type="text/javascript">
    alert("second");
</script>

 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved