js加載與執行機制解析

執行外部腳本的方法:
    1. 如果 async="async":腳本相對於頁面的其餘部分異步地執行(當頁面繼續進行解析時,腳本將被執行)
     2.如果不使用 async 且 defer="defer":腳本將在頁面完成解析時執行
     3.如果既不使用 async 也不使用 defer:在瀏覽器繼續解析頁面之前,立即讀取並執行腳本

阻塞特性:

如果既不使用 async 也不使用 defer,當瀏覽器在執行JS 代碼時,不能同時做其他任何事情,無論其代碼是內嵌的還是外部的。

腳本位置:

瀏覽器在碰到一個引入外部JS 文件的<script>標籤時會停下所有工作來下載並解析執行它,在這個過程中,頁面渲染和用戶交互完全被阻塞了,爲了避免頁面加載時的停頓甚至空白頁的出現,JS 腳本應儘量放置在頁面底部。

<html>
<head>
<title></title>
<!-- 這裏順便說一下,推薦把css文件放在head裏,因爲頁面渲染需要css -->
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>
<body>

<p>頁面內容</p>

<!-- 推薦把js放在頁面底部: -->
<script type="text/javascript" src="file.js"></script>
</body>
</html>

組織腳本:

        爲了改善上面的阻塞情況,應儘可能的減少頁面中<script>標籤的出現次數,這同時也是考慮到HTTP 請求會帶來額外的性能開銷,也就是說應減少頁面中外鏈腳本的數量。也可以手動合併你的多個JS 文件,也可採用類似Yahoo! combo handler 這樣的實時在線服務來實現,例如下面的這個<script>標籤實際上便載入了3個JS 文件:

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

無阻塞的腳本:

        爲了阻塞狀況,這裏提供了幾個實現並行下載JS 腳本的方案。

1. 延遲的腳本

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

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

2. 動態腳本元素

      通過DOM 動態地創建<script>元素並插入到文檔中,文件在該元素被添加到頁面時開始下載,這樣 無論在何時啓動下載,文件的下載和執行過程不會阻塞頁面其他進程。不過要注意使用這種方式加載的代碼會立刻執行,這樣需清楚的瞭解各文件的作用以及合理的執行順序,此時跟蹤並確保腳本下載完成並準備就緒是很有必要的,非IE瀏覽器會在<script>元素接收完成時觸發一個load 事件,而IE 下則會觸發一個readystatechange 事件並通過readyState 屬性加以判斷便可。以下是兼容地動態加載一個JS 腳本的函數:

function loadScript(url, callback) {  
    var script = document.createElement('script');  
    script.type = 'text/javascript';  
    if (script.readyState) {  //IE  
        script.onreadystatechange = function() {  
            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);  
}
也可以將loadScript() 的執行串聯起來:
loadScript('file1.js', function() {  
    loadScript('file2.js', function() {  
        loadScript('file3.js', function() {  
            //全部載入後的操作...  
        } );  
    } );  
} );  

3. XMLHttpRequest 腳本注入

即通過AJAX 方式加載,不過這種方式無法實現跨域加載,不適用於大型網站。







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