高性能javascript讀書筆記(一 加載和運行)

第一章 加載和運行javascript

 <script>標籤的出現使整個頁面因腳本解析,運行而出現等待。不論實際的javascript代碼是內聯的仍是包含在一個不相關的外部文件中,頁面下載和解析必須停下,等待腳本完成這些處理,而後才能繼續,由於腳本可能在運行過程當中修改頁面內容。document.write();html

 <script>標籤能夠放在<head>裏面,可是若是咱們放了不少文件在head裏,每一個<script>都會阻塞頁面的解析,直到他完整的下載並運行了外部的javascript文件。而且瀏覽器在遇到<body>標籤以前是不會渲染頁面的任何部分,因此這樣致使了一個能夠察覺的延遲。每一個js文件都有一個下載和運行的時間。java

IE8,FF3.5, Safari4 chrome2容許並行下載js文件,一個<script>標籤下載外部資源,不會阻塞其餘<script>標籤。可是,javascript的下載仍然要阻塞其餘資源的下載過程,例如圖片。即便腳本之間的下載過程互補阻塞,頁面仍要等待全部javascript代碼下載並執行完成後才能繼續。chrome

推薦:將全部<script>代碼放在儘量接近<body>標籤底部的位置,儘可能減小對整個頁面下載的影響。api

限制頁面的<script>的總數也能夠改善性能。瀏覽器

 減小引用外部腳本文件的數量,每一個http請求都會產生額外的性能負擔,下載一個100KB的文件比下載四個25KB的文件要快,能夠打包將這些文件整合成一個文件服務器

Yahoo!建立了"聯合句柄"。任何一個網站可使用聯合句柄url指出包含哪些文件。app

src="http://yui.yahooapis.com/combo/hahoo.min.js&2.70/build/event-min.js"異步

 此代碼只有一個script標籤,在頁面底部,加載多個javascript,這是在html頁面中包含多個外部javascript的最佳方法。函數

 

非阻塞腳本:等頁面加載以後,再加載javascript代碼,意味着在windowload事件發出以後開始下載代碼,

 Deferred script腳本

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

帶有Defer屬性的script標籤可放在文檔的任何位置,對應的javascript文件將在<script>解析時啓動下載,但代碼不會被執行,直到DOM加載完成(onload事件句柄被調用以前)

當一個deferjavascript 文件被下載時,他不會阻塞瀏覽器的其餘處理程序,因此文件可與頁面的其餘資源一塊兒並行下載。(IEFF3.5支持)

<script defer> alert("deffer"); </script>

<script> alert("next"); </script>

<script defer> window.onload=function(){alert(「widow」)}</script>

順序是   next   deffer window  

注意:標記問defer的不是第二個運行的,是在onload事件句柄處理以前被調用的。

 

Dynamic script elements 動態腳本元素

新的script元素加載.js原文件,此文件當元素添加到頁面以後馬上開始下載。不管在何處啓動下載,文件的下載和運行都不會阻塞其餘頁面處理過程。<script>事件有一個readyState屬性,有五種取值:

uninitialized 默認狀態

loading 下載開始

loaded 下載完成

interactive下載完成尚不可用

complete 因此數據已準備好

在script元素的生命週期,readyState的這些取值並不必定都會被用到,對感興趣loaded complete,

IE對readyState值所表示的最終狀態並不一致,在readyState事件中,檢查兩種狀態,當其中一種出現時,刪除readystatechange事件句柄。

封裝的函數實現javascript文件的動態加載:

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;//刪除readystatechange事件句柄,保證事件不會被處理兩次       callback();         }       }    }else{//others     script.onload=function(){     callback();   } } script.src=url; document.getElementsByTagName("head")[0].appendChild(script); }

  

在頁面中動態加載不少javascript文件,瀏覽器不能保證文件加載的順序

因此主流瀏覽器之中,只有FF Opera會保證腳本按照指定的順序執行,其餘瀏覽器將按照服務器返回他們的次序下載並運行不一樣的代碼文件。

串聯起來:

loadScript(「file.js」, function (){
(「file1.js」, function(){
(「file2.js」,function(){
Alert(「fd」); });});})

缺點:file可用以後,執行file1,以後再執行file2, 方法可行,可是若是要下載和執行的文件比較多,仍是比較麻煩。

若是是多個文件次序十分重要,更好的辦法是將這些文件按照正確的次序鏈接成一個文件,獨立文件能夠一次性下載因此代碼,因爲這是異步的,因此沒有什麼損失。

(動態腳本加載是非阻塞javascript下載中最多見的,由於能夠跨瀏覽器,簡單易用。)

 

XMLHttpRequest Script Injection     XHR腳本注入

首先建立XHR對象,而後下載javascript文件,接着用動態<script>元素將javascript代碼注入頁面。

var xhr = new XMLHttpRequest();

xhr.open("get", "file1.js", true);

xhr.onreadyStatechange=function(){

  if(xhr.readyState==4){

    if(xhr.status>=200&&xhr.status<300||xhr.status==304){

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

      script.type="text/javascript";

      script.text=xhr.responseText;

      document.body.appendChild(script);

    }

  }

}

xhr.send(null);

 

向服務器發送一個獲取file.js文件的GET請求,onreadystatechange事件處理函數檢查readyState是否是4,而後檢查HTTP狀態碼是否是有效(2XX表示有效的迴應,304表明響應),若是收到了一個有效響應,就建立script標籤,將他的文本屬性設置爲從服務器收到的responseText字符串,實際會建立一個帶有內聯代碼的script 一旦新script元素被添加到文檔,代碼被執行,並準備使用。

 

優勢:能夠下載不當即執行的javascript代碼,因爲代碼返回在script標籤以外,它下載後不會自動執行,你能夠推遲執行,直到一切都準備好。

全部瀏覽器中都不會異常

缺點:javascript文件都必須與頁面放置一個域內。

 

推薦的向頁面加載大量的Javascript的方法:

1,先包含動態加載javascript所需的代碼,而後加載頁面初始化所須要的除javascript之外的部分。這部分代碼儘可能小,可能只包含一個loadScript()函數,它下載和運行很是迅速,不會對頁面形成很大幹擾,當初始代碼準備好了,再用它加載其餘的javascript代碼。

 

<script type="text/javascript" src="load.js></script>
<script type="text/javascript">
   loadScript("the-rest.js", function(){
        Application.init();        
    };
</script>
相關文章
相關標籤/搜索