天天看點

Javascript在頁面加載時的執行順序

一、在HTML中嵌入Javasript的方法

  1. 直接在Javascript代碼放在标記對<script>和</script>之間
  2. 由<script />标記的src屬性制定外部的js檔案
  3. 放在事件處理程式中,比如:

    <p onclick="alert('我是由onclick事件執行的Javascript')">點選我</p>

  4. 作為URL的主體,這個URL使用特殊的Javascript:協定,比如:

    <a href="javascript:alert('我是由javascript:協定執行的javascript')">點選我</a>

  5. 利用javascript本身的document.write()方法寫入新的javascript代碼
  6. 利用Ajax異步擷取javascript代碼,然後執行

第3種和第4種方法寫入的Javascript需要觸發才能執行,是以除非特别設定,否則頁面加載時不會執行。

二、Javascript在頁面的執行順序

  1. 頁面上的Javascript代碼是HTML文檔的一部分,是以Javascript在頁面裝載時執行的順序就是其引入标記<script />的出現順序, <script />标記裡面的或者通過src引入的外部JS,都是按照其語句出現的順序執行,而且執行過程是文檔裝載的一部分。
  2. 每個腳本定義的全局變量和函數,都可以被後面執行的腳本所調用。
  3. 變量的調用,必須是前面已經聲明,否則擷取的變量值是undefined。
    <script type="text/javscrpt">//<![CDATA[
    alert(tmp);  //輸出 undefined
    var tmp = 1;
    alert(tmp);  //輸出 1
    //]]></script>           
  4. 同一段腳本,函數定義可以出現在函數調用的後面,但是如果是分别在兩段代碼,且函數調用在第一段代碼中,則會報函數未定義錯誤。
    <script type="text/javscrpt">//<![CDATA[
    aa();            //浏覽器報錯
    //]]></script>
    <script type="text/javscrpt">//<![CDATA[
    aa();			//輸出 1 
    function aa(){alert(1);}
    //]]></script>           
  5. document.write()會把輸出寫入到腳本文檔所在的位置,浏覽器解析完documemt.write()所在文檔内容後,繼續解析document.write()輸出的内容,然後在繼續解析HTML文檔。
    <script type="text/javascript">//<![CDATA[
        document.write('<script type="text/javascript" src="test.js"><\/script>');
        document.write('<script type="text/javascript">');
        document.write('alert(2);')
        document.write('alert("我是" + tmpStr);');
        document.write('<\/script>');
        //]]></script>
      <script type="text/javascript">//<![CDATA[
        alert(3);
        //]]></script>           
    test.js的内容是:
    var tmpStr = 1;
        alert(tmpStr);           
    • 在Firefox和Opera中的彈出值的順序是:1、2、我是1、3
    • 在IE中彈出值的順序是:2、1、3,同時浏覽器報錯:tmpStr未定義

    原因可能是IE在document.write時,并未等待加載SRC中的Javascript代碼完畢後,才執行下一行,是以導緻2先彈出,并且執行到document.write(’document.write("我是" + tmpStr)’)調用tmpStr時,tmpStr并未定義,進而報錯。

    解決這個問題,可以利用HTML解析是解析完一個HTML标簽,再執行下一個的原理,把代碼拆分來實作:

    <script type="text/javascript">//<![CDATA[
        document.write('<script type="text/javascript" src="test.js"><\/script>');
        //]]></script>
      <script type="text/javascript">//<![CDATA[
        document.write('<script type="text/javascript">');
        document.write('alert(2);')
        document.write('alert("我是" + tmpStr);');
        document.write('<\/script>');
        //]]></script>
      <script type="text/javascript">//<![CDATA[
        alert(3);
        //]]></script>           
    這樣IE下和其他浏覽器輸出值的順序都是一直的了:1、2、我是1、3。

三、如何改變Javascript在頁面的執行順序

  1. 利用onload
    <script type="text/javascript">//<![CDATA[
    window.onload = f;
    function f(){alert(1);}
    alert(2);
    //]]></script>           

    輸出值順序是 2、1。

    需要注意的是,如果存在多個winodws.onload的話,隻有最有一個生效,解決這個辦法是:

    window.onload = function(){f();f1();f2();.....}           
    利用2級DOM事件類型
    if(document.addEventListener){
    window.addEventListener('load',f,false);
    window.addEventListener('load',f1,false);
    ...
    }else{
    window.attachEvent('onload',f);
    window.attachEvent('onload',f1);
    ...
    }           
  2. IE中可以利用defer,defer作用是把代碼加載下來,并不立即執行,等文檔裝載完畢之後再執行,有點類似window.onload,但是沒有window.onload那樣的局限性,可以重複使用,但是隻在IE中有效,是以上面的例子可以修改成為
    <script type="text/javascript">//<![CDATA[
    document.write('<script type="text/javascript" src="test.js"><\/script>');
    document.write('<script type="text/javascript" defer="defer">');
    document.write('alert(2);')
    document.write('alert("我是" + tmpStr);');
    document.write('<\/script>');
    //]]></script>
    <script type="text/javascript">//<![CDATA[
    alert(3);
    //]]></script>           

    這樣IE就不報錯了,輸出值的順序變成:1、3、2、我是1

    當HTML解析器遇到一個腳本,它必須按正常終止對文檔的解析并等待腳本執行。為了解決這個問題HTML4标準定義了defer。通過defer來提示浏覽器可以繼續解析HTML文檔,并延遲執行腳本。這種延遲在腳本從外部檔案載入時非常有用,讓浏覽器不必等待外部檔案全部載入之後才繼續執行,能有效的提高性能。IE是目前唯一支援defer屬性的浏覽器,但IE并沒有正确的實作了defer屬性,因為延遲的腳本總是被延遲,直到文檔結束,而不是隻延遲到下一個非延遲的腳本。這意味着,IE中延遲的腳本的執行順序相當混亂,并且不能定義任何後面非延遲腳本并須的函數和變量。在IE中所有的defer的腳本執行時間應該都是HTML文檔樹建立以後,window.onload之前。

  3. 利用Ajax。

    因為xmlhttpRequest能判斷外部文檔加載的狀态,是以能夠改變代碼的加載順序。

部落格園大道至簡

http://www.cnblogs.com/jams742003/

轉載請注明:部落格園

繼續閱讀