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

原文: http://blog.csdn.net/kylinbl/article/details/6160587


 操做HTML DOM文檔的一個難題是,你的JavaScript代碼可能在DOM徹底載入以前運行,這會致使你的代碼產生一些問題。頁面加載時瀏覽器內部操做的順序大體是這樣的:
  1. HTML被解析。
  2. 外部腳本/樣式表被加載。
  3. 文檔解析過程當中內聯的腳本被執行。
  4. HTML DOM構造完成。
  5. 圖像和外部內容被加載。
  6. 頁面加載完成。
  頭部包含的和從外部文件中載入的腳本實際上在HTML DOM構造好以前就執行了。正如前面提到的,這一個問題是很重要的,由於在那兩種地方的執行的全部腳本將不能訪問DOM。可喜的是,存在許多繞開這一問題的辦法。 javascript

html中的加載是自上而下 html

如 alert.html 中 java

 


如下爲引用內容:
<html>
<head>
<script type="text/javascript">
alert(1);
</script>
<script type="text/javascript" src="a.js"></script>(在a.js中有一句alert(2))
</head>

 

對JS腳本與CSS樣式的加載 瀏覽器

一、IE下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染是同時進行的。
      二、在渲染到頁面的某一部分時,其上面的全部部分都已經下載完成(並非說全部相關聯的元素都已經下載完)。
      三、若是遇到語義解釋性的標籤嵌入文件(JS腳本,CSS樣式),那麼此時IE的下載過程會啓用單獨鏈接進行下載。
      四、而且在下載後進行解析,解析過程當中,中止頁面全部往下元素的下載。
      五、樣式表在下載完成後,將和之前下載的全部樣式表一塊兒進行解析,解析完成後,將對此前全部元素(含之前已經渲染的)從新進行渲染。
      六、JS、CSS中若有重定義,後定義函數將覆蓋前定義函數。 異步

 


如下爲引用內容:
<body>
姓名:<input id="a"/>
<script>alert(3)</script>
</body>

 

則執行順序是1,2,3,姓名:<input id="a"/>,若是要在 "姓名:<input id="a"/>,"上面寫 函數

 


如下爲引用內容:
<script>document.getElementById("a")</script>

 

返回的是null,但在下面寫能夠,儘管alert(3)先於它執行 spa

注意:只要是方法都是加載完後執行,若寫onload="a()",此方法是以上的1,2,3....所有執行完後才執行 .net

在HTML中嵌入Javasript xml

一、直接在Javascript代碼放在標記對<script>和</script>之間 htm

二、由<script />標記的src屬性制定外部的js文件

三、放在事件處理程序中,好比:

 


如下爲引用內容:
<p onclick="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中的彈出值的順序是:一、二、我是一、3

在IE中彈出值的順序是:二、一、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下和其餘瀏覽器輸出值的順序都是一直的了:一、二、我是一、3。

改變Javascript的執行順序

一、利用onload


如下爲引用內容:
<script type="text/javascript">//<![CDATA[
window.onload = f;
function f(){alert(1);}
alert(2);
//]]></script>

輸出值順序是 二、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中能夠利用deferdefer做用是把代碼加載下來,並不當即執行,等文檔裝載完畢以後再執行,有點相似onload,可是沒有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

三、利用Ajax。

由於xmlhttpRequest能判斷外部文檔加載的狀態,因此可以改變代碼的加載順序。

相關文章
相關標籤/搜索