js 載入與運行順序

來源:互聯網
上載者:User

標籤:定義   syntax   整理   type   ber   test   line   覆蓋   機制   

今天在查資料的時候,看到了一篇不錯的文章,這裡我轉載下。一是為了以後自己能夠回過頭來找的時候好找,二是看看能否協助園子裡的小夥伴解決些問題。好了,不多說了,下面開始吧!

 

 

JavaScript是一種描述型指令碼語言,它不同於java或C#等編譯性語言,它不需要進行編譯成中繼語言,而是由瀏覽器進行動態地解析與執行。如果你不能理解javaScript語言的運行機制,或者簡單地說,你不能掌握javascript的執行順序,那你就猶如伯樂駕馭不了千裡馬,讓千裡馬脫韁而出,四處亂竄。

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

1、代碼塊

JavaScript中的代碼塊是指由<script>標籤分割的程式碼片段。例如:

 

?
123456 <script type="text/javascript">      alert("這是代碼塊一");</script><script type="text/javascript">      alert("這是代碼塊二");</script>

 

JS是按照代碼塊來進行編譯和執行的,代碼塊間相互獨立,但變數和方法共用。什麼意思呢? 舉個例子,你就明白了:

 

?
123456789 <script type="text/javascript">      alert(str);//因為沒有定義str,所以瀏覽器會出錯,下面的不能運行      alert("我是代碼塊一");//沒有運行到這裡      var test = "我是代碼塊一變數";</script><script type="text/javascript">      alert("我是代碼塊二"); //這裡有運行到      alert(test); //彈出"我是代碼塊一變數"</script>

上面的代碼中代碼塊一中運行報錯,但不影響代碼塊二的執行,這就是代碼塊間的獨立性,而代碼塊二中能調用到代碼一中的變數,則是塊間共用性。

 

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

JS中的函數定義分為兩種:聲明式函數與賦值式函數。

 

?
123456789 <script type="text/javascript">     function Fn(){ //聲明式函數                  }              var Fn = function{  //賦值式函數                  }</script>

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

 

3、先行編譯期與執行期

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

先行編譯期JS會對本代碼塊中的所有聲明的變數和函數進行處理(類似與C語言的編譯),但需要注意的是此時處理函數的只是聲明式函數,而且變數也只是進行了聲明但未進行初始化以及賦值。

 

?
12345678910 <script type="text/javascript">     Fn();  //執行結果:"執行了函數2",同名函數後者會覆蓋前者     function Fn(){ //函數1        alert("執行了函數1");     }              function Fn(){  //函數2        alert("執行了函數2");     }</script>
?
12345678910 <script type="text/javascript">      Fn();  //執行結果:"執行了聲明式函數",在先行編譯期聲明函數及被處理了,所以即使Fn()調用函數放在聲明函數前也能執行。      function Fn(){ //聲明式函數         alert("執行了聲明式函數");      }               var Fn = function(){  //賦值式函數         alert("執行了賦值式函數");      }</script>
?
12345678910 //代碼塊一<script type="text/javascript">      alert(str);//瀏覽器報錯,但並沒有彈出資訊窗</script>//代碼塊二<script type="text/javascript">      alert(str); //彈窗"undefined"      var str = "aaa";</script>//js在前置處理期間對變數進行了聲明處理,但是並沒有進行初始化與賦值,所以導致代碼塊二中的變數是unfiened的,而代碼一中的變數是完全不存在的,所以瀏覽器報錯。

理解了上面的幾個術語,相信大家對JS的運行機制已經有了個大概的印象了,現在我們來看個例子:

 

 

?
12345678 <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代碼應該放在前面的<script>代碼塊中,而需要在頁面元素載入完後的js放在元素後面,body標籤的onload事件是在最後執行的。

 

?
123456789101112 <script type="text/javascript">    alert("first");    function Fn(){        alert("third");    }</script>       <script type="text/javascript">    alert("second");</script>

 

js 載入與運行順序

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.