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

直接在Javascript代碼放在標記對<script>和</script>之間  
由<script />標記的src屬性制定外部的js文件  
放在事件處理程序中,比如:<p οnclick="alert('我是由onclick事件執行的Javascript')">點擊我</p>  
作爲URL的主體,這個URL使用特殊的Javascript:協議,比如:<a href="javascript:alert('我是由javascript:協議執行的javascript')">點擊我</a>  
利用javascript本身的document.write()方法寫入新的javascript代碼  
利用Ajax異步獲取javascript代碼,然後執行  
第3種和第4種方法寫入的Javascript需要觸發才能執行,所以除非特別設置,否則頁面加載時不會執行。  
二、Javascript在頁面的執行順序  
  
頁面上的Javascript代碼是HTML文檔的一部分,所以Javascript在頁面裝載時執行的順序就是其引入標記<script />的出現順序, <script />標記裏面的或者通過src引入的外部JS,都是按照其語句出現的順序執行,而且執行過程是文檔裝載的一部分。  
每個腳本定義的全局變量和函數,都可以被後面執行的腳本所調用。  
變量的調用,必須是前面已經聲明,否則獲取的變量值是undefined。  
<script type="text/javscrpt">//<![CDATA[  
alert(tmp);  //輸出 undefined  
var tmp = 1;  
alert(tmp);  //輸出 1  
//]]></script>  
同一段腳本,函數定義可以出現在函數調用的後面,但是如果是分別在兩段代碼,且函數調用在第一段代碼中,則會報函數未定義錯誤。  
<script type="text/javscrpt">//<![CDATA[  
aa();            //瀏覽器報錯  
//]]></script>  
<script type="text/javscrpt">//<![CDATA[  
aa();           //輸出 1   
function aa(){alert(1);}  
//]]></script>  
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在頁面的執行順序  
  
利用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);  
...  
}  
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之前。  
利用Ajax。  
因爲xmlhttpRequest能判斷外部文檔加載的狀態,所以能夠改變代碼的加載順序。  
摘自:http://dancewithnet.com/2007/03/22/order-of-execution-of-javascript-on-web/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章