這篇文章主要介紹了關於Javascript載入的解析,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下 1. 瀏覽器載入 (1) 同步載入 在網頁中,瀏覽器載入js檔案的方式是透過標籤。如下所示:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">//内嵌脚本 <script type="text/javacript"> // code here! //加载外部脚本 登入後複製標籤很方便,只要加入後,瀏覽器便可讀取並運行,但是在讀取的時候,瀏覽器是按照<script>標籤的出現順序,讀取Javascript文件,然後立即運行,導致在多個文件相互依賴的情況下,依賴性最小的文件必須放在最前面,依賴性最大的必須放在最後面,否則代碼會報錯,這一點,想必大家在使用bootstrap的時候都深有體會。另一方面,瀏覽器採用同步模式載入<script>標籤,也就是說,頁面會等待JavaScript檔案載入完成,然後再執行後面的程式碼。當存在很多<script>標籤時,瀏覽器無法同時讀取,必須讀完一個再讀取另一個,造成讀取時間大大延長,頁面回應緩慢,影響使用者體驗。同步模式又稱為阻塞模式,會阻止瀏覽器的後續處理,停止後續的解析,只有目前載入完成,才能進行下一步操作,所以預設同步執行才是安全的。但這樣如果js中有輸出document內容、修改DOM、重定向等行為,就會造成阻塞。所以一般建議把<script>標籤放在<body>結尾處,這樣能減少頁面阻斷。 </p><p><strong> (2)非同步載入</strong></p><p> 為了解決這個問題,ES5中採用了DOM方法,<strong>動態載入JavaScript腳本檔案</strong>。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">function loadScript(url) { var script = document.createElement("script"); script.type="text/javascript"; script.src=url; document.body.appendChild(script); }</pre><div class="contentsignin">登入後複製</div></div><p> 這種方式透過建立一個新的<script>標籤,並設定其src屬性,非同步讀取javacript檔案</p><p>這樣不會造成頁面阻塞,但會有另一個問題,如果其他腳本檔案依賴它,此時無法保證此腳本何時能夠載入完畢。 </p><p> 另一種載入方式是利用<strong>defer和async</strong>屬性,讓腳本非同步載入。渲染引擎遇到這一行命令,就會開始下載外部腳本,但不會等它下載和執行,而是直接執行後面的命令。 defer和async的區別是: defer要等到整個頁面在內存中正常渲染結束(DOM結構完全生成,以及其他腳本執行完成),才會執行;async一旦下載完成,渲染引擎就會中斷渲染,執行這個腳本以後,再繼續渲染。即defer是渲染完再執行,async是下載完就執行。另外,如果有多個defer腳本,會按照它們在頁面中出現的順序加載,而多個async腳本是不能保證加載順序的。 </p><p> IE9及以下版本在延遲實作上有一些相當糟糕的錯誤,導致執行順序無法保證。 如果你需要支援<= IE9,我建議不要使用defer,如果執行順序很重要,請包含沒有屬性的腳本。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre><script src="path/demo.js" defer> 登入後複製 如何選用defer和async。如果使用的script是個模組,且不依賴任何其它script檔案時使用async;如果腳本依賴其它script或則被其它script依賴,就使用defer;倘若腳本檔案很小且被一個async script依賴,就使用內嵌script把該檔案放在所有async script前面。 另外一種方法是onload事件的非同步載入。 (function(){ if(window.attachEvent) { window.attachEvent("load", asyncLoad); } else if(window.addEventListener) { window.addEventListener("load", asyncLoad); } else { window.onload = asyncLoad; } var asyncLoad = function() { var script = document.createElement("script"); script.type="text/javascript"; script.async = true; script.src = ('https:'==document.location.protocol ? 'https://ssl' : 'http:www') + '.baidu.com/demo.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); }; )();登入後複製 這個方法是將插入script的方法放在一個函數裡面,然後放在window的onload方法裡面執行,這樣就解決了阻塞onload事件的觸發問題。 由於Javascript的動態性,還有很多非同步載入方法:XHR Injection、XHR eval、Script In Iframe、document.write("<p> XHR注入:透過XMLHttpRequest來取得Javascript,然後建立一個script元素插入到DOM結構中。 ajax請求成功後設定script.text為請求成功後回傳的responseText.</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">var createXHR = function() { var obj; if(window.XMLHttpRequest) obj = new XMLHttpRequest(); else obj = new ActiveObject("Microsoft.XMLHTTP"); return obj; }; var xhr = createXML(); xhr.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true); xhr.send(); xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200) { var script = document.createElement("script"); script.text = xhr.requestText; document.getElementsByTagName("head")[0].appendChild(script); } }</pre><div class="contentsignin">登入後複製</div></div><p>XHR eval(): 與XHR Injection對responseText的執行方式不同,直接把responseText放在eval()函式裡面執行。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">var createXHR = function() { var obj; if(window.XMLHttpRequest) obj = new XMLHttpRequest(); else obj = new ActiveObject("Microsoft.XMLHTTP"); return obj; }; var xhr = createXML(); xhr.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true); xhr.send(); xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200) { eval(xhr.responseText); $('#btn').click(function() { alert($(this).text()); }); } }</pre><div class="contentsignin">登入後複製</div></div><p> Script In Iframe: 在父視窗插入一個iframe元素,然後再iframe中執行載入JS的操作。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">var insertJS = function(){ alert($); }; var iframe = document.createElement("iframe"); document.body.appendChild(iframe); var doc = iframe.contentWindow.document;//获取iframe中的window doc.open(); doc.write("<script>var insertJS = function(){};<\/script><body onload='insertJS()'></body>"); doc.close();</pre><div class="contentsignin">登入後複製</div></div><p><strong>2. 延遲載入</strong><br/></p><p> 有些JS代码在某些情况下需要使用,并不是页面初始化的时候就要用到。延迟加载就是为解决这个问题。将JS切分成许多模块,页面初始化时只将事件处理程序添加到UI元素上,然后其它JavaScript代码的加载延迟到第一次用户交互或者其他条件需要用到的时候再加载。类似图片的懒加载。这样做的目的是可以渐进式地载入页面,尽可能快地为用户提供目前需要的信息,其余部分的内容可以在用户浏览该页面时在后台载入。</p><p> JavaScript的加载分为两个部分:下载和执行脚本,异步加载只解决了下载的问题,但是代码在下载完成后就可能会立即执行,在执行过程中浏览器储与阻塞状态,响应不了任何需求。为了解决JavaScript延迟加载的问题,可以利用异步加载缓存起来,所以不会立即执行,然后在第一次需要的时候再执行。</p><p> 第二部分内容的载入可以用创建动态脚本的形式:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">window.onload = function() { var script = document.createElement("script"); script.type="text/javascript"; script.src="demo.js"; document.documentElement.firstChild.appendChild("script"); }</pre><div class="contentsignin">登入後複製</div></div><p><strong>3. 按需加载</strong></p><p> 可以通过创建一个require方法,包含需要加载的脚本名称和附加脚本加载完成后需要执行的回调函数。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">function require(file, callback) { var script = document.getElementsByTagName("script")[0]; var newjs = document.createElement("script"); newjs.onload= function() { callback(); }; newjs.src=file; script.parentNode.insertBefore(newjs, script); }</pre><div class="contentsignin">登入後複製</div></div><p>以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!</p> <p>相关推荐:</p> <p><a title="关于javascrip的立即执行函数的解析" href="//m.sbmmt.com/js-tutorial-406380.html" target="_blank">关于javascrip的立即执行函数的解析</a><br></p> <p><a title="深入理解JS正则表达式之REGEXP对象属性的解析" href="//m.sbmmt.com/js-tutorial-406378.html" target="_blank">深入理解JS正则表达式之REGEXP对象属性的解析</a><br></p>