天天看點

JAVASCRIPT高性能執行和加載(阻塞特性)

[size=medium][color=blue]阻塞特性:

JS 有個很無語的阻塞特性,就是當浏覽器在執行JS 代碼時,不能同時做其他任何事情,無論其代碼是内嵌的還是外部的。

腳本位置:

浏覽器在碰到一個引入外部JS 檔案的<script>标簽時會停下所有工作來下載下傳并解析執行它,在這個過程中,頁面渲染和使用者互動完全被阻塞了,為了避免頁面加載時的停頓甚至空白頁的出現,JS 腳本應盡量放置在頁面底部,這點很重要:

<html>

<head>

<title>無标題文檔</title>

<link rel="stylesheet" type="text/css" href="styles.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" />

</head>

<body>

<p>頁面的内容。。。</p>

<!-- 推薦的位置,頁面底部: -->

<script type="text/javascript" src="file1.js"></script>

<script type="text/javascript" src="file2.js"></script>

<script type="text/javascript" src="file3.js"></script>

</body>

</html>

組織腳本:

為了改善上面的阻塞情況,應盡可能的減少頁面中<script>标簽的出現次數,這同時也是考慮到HTTP 請求會帶來額外的性能開銷,也就是說應減少頁面中外鍊腳本的數量。

你可以手動合并你的多個JS 檔案,也可采用類似Yahoo! combo handler 這樣的實時線上服務來實作,例如下面的這個<script>标簽實際上便載入了3個JS 檔案:

<html>

<head>

<title>無标題文檔</title>

<link rel="stylesheet" type="text/css" href="styles.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" />

</head>

<body>

<p>頁面的内容。。。</p>

<!-- 推薦的位置,頁面底部: -->

<script type="text/javascript" src="http://yui.yahooapis.com/combo?file1.js&file2.js&file3.js"></script>

</body>

</html>

無阻塞的腳本:

為了阻塞狀況,這裡提供了幾個實作并行下載下傳JS 腳本的方案。

1. 延遲的腳本

HTML4 為<script>标簽定義了一個defer 屬性,它能使這段代碼延遲執行,然而該屬性隻有IE4+ 和Firefox 3.5+ 支援。聲明了defer 屬性的<script>會在DOM加載完成,window.onload 事件觸發前被解析執行:

<script type="text/javascript" src="file1.js" defer></script>

2. 動态腳本元素

這是最通用的解決方案,通過DOM 動态地建立<script>元素并插入到文檔中,檔案在該元素被添加到頁面時開始下載下傳,這樣 無論在何時啟動下載下傳,檔案的下載下傳和執行過程不會阻塞頁面其他程序。

不過要注意使用這種方式加載的代碼會立刻執行,這樣需清楚的了解各檔案的作用以及合理的執行順序,此時跟蹤并確定腳本下載下傳完成并準備就緒是很有必要的,非IE浏覽器會在<script>元素接收完成時觸發一個load 事件,而IE 下則會觸發一個readystatechange 事件并通過readyState 屬性加以判斷便可。以下是相容地動态加載一個JS 腳本的函數:了:

function load_script(url, callback)

{ var script = document.createElement("script");

script.type = "text/javascript";

if (script.readyState)

{ //IE

script.onreadystatechange = functio()

{

if (script.readyState == "loaded" script.readyState == "complete")

{

script.onreadystatechange = null;

callback();

}

}

}

else

{ //others

script.onload = function(){

callback(); }

}

script.src = url;

document.getElementsByTagName("head")[0].appendChild(script);

}

你可以将這個函數儲存至一個load_script.js 檔案,然後用該函數來加載其他的腳本,當要加載多個腳本時,為了確定正确的加載順序,可以将load_script() 的執行串聯起來,最後如前面說到的放至頁面的底部,這便是一個完美的解決方案了。

<script type="text/javascript"src="load_script.js"></script>

<script type="text/javascript">

load_script("file1.js", function()

{

load_script("file2.js", function()

{

load_script("file3.js", functio() {

//全部載入後的操作...

} );

} );

} );

</script>

3.XMLHttpRequest 腳本注入

即通過AJAX 方式加載,不過這種方式無法實作跨域加載,不适用于大型網站。

推薦的無阻塞模式

我們上面做的這些工作當然也已經被那些牛人們完成了,并寫成了一些優秀的JS 類庫以便我們使用,它們均能很好地解決JS 腳本的阻塞問題,實作并行下載下傳,例如: YUI3、LazyLoad、LABjs 等。[/color][/size]

繼續閱讀