<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # js的并行加載與順序執行   javaScript文件(下面簡稱腳本文件)需要被HTML文件引用才能在瀏覽器中運行。在HTML文件中可以通過不同的方式來引用腳本文件,我們需要關注的是,這些方式的具體實現和這些方式可能會帶來的性能問題。   當瀏覽器遇到(內嵌)`<script>`標簽時,當前瀏覽器無從獲知javaScript是否會修改頁面內容。因此,這時瀏覽器會停止處理頁面,先執行javaScript代碼,然后再繼續解析和渲染頁面。同樣的情況也發生在使用 `src` 屬性加在javaScript的過程中(即外鏈 javaScript),瀏覽器必須先花時間下載外鏈文件中的代碼,然后解析并執行它。在這個過程中,頁面渲染和用戶交互完全被阻塞了。   也就是說:每當瀏覽器解析到`<script>`標簽(無論內嵌還是外鏈)時,瀏覽器會(一根筋地)優先下載、解析并執行該標簽中的javaScript代碼,而阻塞了其后所有頁面內容的下載和渲染。 ## 五種引用腳本的方式: 1. Script DOM Element。 動態插入`<script>`,不會阻塞,但無法保持執行順序。但唯有Firefox可以保持執行順序,但也差點在Firefox 4 nightly的版本中去掉這個特性。 這種技術的重點在于: > 無論在何時啟動下載,文件的下載和執行過程不會阻塞頁面其他進程(包括腳本加載)。 然而這種方法也是有缺陷的。這種方法加載的腳本會在下載完成后立即執行,那么意味著多個腳本之間的運行順序是無法保證的(除了Firefox和Opera)。當某個腳本對另一個腳本有依賴關系時,就很可能發生錯誤了。比如,寫一個jQuery代碼,需要引入jQuery庫,然而你寫的jQuery代碼文件很可能會先完成下載并立即執行,這時瀏覽器會報錯——‘`jQuery未定義`’之類的,因為此時jQuery庫還未下載完成。于是做出以下改進: ~~~ 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{//其他瀏覽器 script.onload=function(){ callback(); }; } script.src=url; document.getElementsByTagName(‘head’)[0].appendChild(script); } ~~~ 上述代碼改進的地方就是增加了一個回調函數,該函數會在相應腳本文件加載完成后被調用。這樣便可以實現順序加載了,寫法如下(假設file2依賴file1,file1和file3相互獨立): `loadScript(‘file1.js’,function(){ loadScript(‘file2.js’,function(){}); }); loadScript(‘file3.js’,function(){}); ` file2會在file1加載完后才開始加載,保證了在file2執行前file1已經準備妥當。而file1和file3是并行下載的,互不影響。 雖然loadScript函數已經足夠好,但還是有些不盡人意的地方——通過分析這段代碼,我們知道,loadScript函數中的順序加載是以腳本的阻塞加載來實現的(正如上述紅字部分指出的那樣)。而我們真正想實現的是——腳本同步下載并按相應順序執行,即并行加載并順序執行。 2. HTML5 async 非阻塞,加載完后立即執行,不保證順序。這個屬性不管有沒有值、值為true或false,都是等同的效果(由于Kyle的推進,不能保證執行順序與其值無關了)。 Google Analytics的新版嵌入代碼就結合使用了上面兩個方案,如: ~~~ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); ~~~ 3. IE partsandspares.co.za defer屬性。不阻塞,可以保證順序,在DOM加載完成后執行(在`DOMContentLoaded`之前)。 4. `<script>`的type屬性設為”script/cache” 非標準的type屬性,使js文件只會被加載而不會執行。需要執行時,創建一個type屬性為”text/JavaScript”的正常`<script>`元素,src設為前面已經加載的js地址即可,執行順序開發者可控(執行時機也完全可控)。類似的方式也有通過`<img>`來做預加載的。 5. `document.write`。文檔流關閉后執行會清空整個頁面。 6. `XHR` 并行加載,執行順序可控,但有同域限制。 ## 基本需求: Steve Souders 和 Nicholas C. Zakas 一起總結了下,認為js加載方案必須解決以下問題: * 支持特性檢測 * 不會重復加載 * 支持并行加載 ## 解決方案: head.js LABjs LABjs庫能幫我們真正地實現“并行加載與順序執行”,推薦寫法如下: ~~~ <script src="LAB.js"></script> <script type="text/javaScript"> $LAB .script("script1.js").wait() .script("script2-a.js") .script("script2-b.js") .wait(function(){ initScript1(); initScript2(); }) .script("script3.js") .wait(function(){ initScript3(); }); </script> ~~~ requireJS ~~~ <script src="require.js"></script>   <script type="text/javaScript">     require([       "script1.js",       "script2-a.js",       "script2-b.js",       "script3.js"      ],      function(){       initScript1();       initScript2();       initScript3();      }     );   </script> ~~~ ## 附錄知識 ### 預編譯期與執行期 JS是按照代碼塊來進行編譯和執行的,**代碼塊間相互獨立,但變量和方法共享**。什么意思呢? 舉個例子,你就明白了: ~~~ <script type="text/javascript"> alert(str);//因為沒有定義str,所以瀏覽器會出錯,下面的不能運行 alert("我是代碼塊一");//沒有運行到這里 var test = "我是代碼塊一變量"; </script> <script type="text/javascript"> alert("我是代碼塊二"); //這里有運行到 alert(test); //彈出"我是代碼塊一變量" </script> ~~~ 上面的代碼中代碼塊一中運行報錯,但不影響代碼塊二的執行,這就是代碼塊間的獨立性,而代碼塊二中能調用到代碼一中的變量,則是塊間共享性。 JS的解析過程分為兩個階段:**預編譯期(預處理)與執行期**。   預編譯期 JS會對本代碼塊(兩個script塊互不影響)中的所有var聲明的變量和函數進行處理(類似與C語言的編譯)   此時處理函數的只是聲明式函數,而且變量也只是進行了聲明但未進行初始化以及賦值。   執行期 會按照代碼塊的順序逐行執行 `代碼塊`: ~~~ <script type="text/javascript"> alert("first"); function Fn(){ alert("third"); } </script> <script type="text/javascript"> alert("second"); </script> ~~~ 可以總結出js執行的順序: ~~~ step 1. 讀入第一個代碼塊。 step 2. 做語法分析,有錯則報語法錯誤(比如括號不匹配等),并跳轉到 step 5。 step 3. 對 var 變量和 function 定義做“預編譯處理”(永遠不會報錯的,因為只解析正確的聲明)。 step 4. 執行代碼段,有錯則報錯(比如變量未定義)。 step 5. 如果還有下一個代碼段,則讀入下一個代碼段,重復 step 2。 step 6. 結束。 ~~~ `加載順序測試代碼:` 根據html文檔流的執行順序, 需要在頁面元素**渲染前**執行的js代碼應該放在`<body>`前面的`<script>`代碼塊中, 需要在頁面**加載完成后**執行的js放在`</body>`元素后邊, `body`的**onload事件是最后執行**的。 ![](![](images/screenshot_1515228812431.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看