Javascript的裝載和執行
通常來說,瀏覽器對於Javascript
的執行有兩大特性:
- 載入後馬上執行
- 執行時會阻塞頁面後續的內容(包括頁面的渲染/其他資源的載入)。於是,如果有多個js檔案被引入,那麼對於瀏覽器來說,這些js檔案被穿行地載入,並一次執行。
因為javascrit
可能會操作HTML文件的DOM樹,所以,瀏覽器一般都不會像並行下載css
檔案並行下載js
檔案,因為這是js
檔案的特殊性造成的。所以,如果你的javascript
像操作後面的DOM元素,基本上來說,瀏覽器都會報錯說物件找不到。因為javascript
執行時,後面的html
被阻塞住了,DOM
樹時還沒有後面的DOM節點。所以程式也就報錯了。
傳統的方式
所以,當你在程式碼中寫下如下程式碼:
<script type="text/javascript" src="http://coolshell.cn/asyncjs/alert.js"></script>
基本上來說,head
裡的script
標籤會阻塞後續資源的載入以及整個頁面的生成。
所以,你知道為啥那麼有很多網站把javascript
放在網頁的最後面了,要麼就是動用window.onload
或是$(document).ready(function(){})
之類的事件。
另外,因為絕大多數哦的javascrit
程式碼並不需要等頁面,即:非同步載入。那我們如何非同步載入呢?
document.write
方式
於是,你可能以為document.write()
這種方式能夠解決阻塞問題。你當然會覺得,document.write
了的script
標籤後就可以執行後面的東西了,者沒錯。對於在同一個script
標籤例的javascript
的程式碼來說,是這樣的,但是對於整個頁面來說,這個還是會阻塞,下面時一段測試程式碼:
<script type="text/javascript" language="javascript">
function loadjs(script_filename) {
document.write('<' + 'script language="javascript" type="text/javascript"');
document.write(' src="' + script_filename + '">');
document.write('<'+'/script'+'>');
alert("loadjs() exit...");
}
var script = 'http://coolshell.cn/asyncjs/alert.js';
loadjs(script);
alert("loadjs() finished!");
</script>
<script type="text/javascript" language="javascript">
alert("another block");
</script>
依此彈出的對話方塊為:
loadjs() exit...
loadjs() finished!
hello world
another block
然後才會顯示頁面。
script
的defer
和async
屬性
IE自從IE6就支援defer
,如:
<script defer type="text/javascript" src="./alert.js" ></script>
對於IE來說,這個標籤會讓IE並行下載js檔案,並且把其執行hold到了整個DOM裝載完畢(DOMContentLoaded),多個defer
的script
在窒息感時也會按照其出現的順序來執行。但是因為這個defer
只時IE專用,所以一般用的比較少。
而我們標磚的HTML5也加入了一個非同步載入javascript
的屬性:async
,無論你對它都什麼樣的值,只要它出現,它就開始非同步載入js檔案。但是,async
的非同步載入會有一個嚴重的問題,那就是它忠實地鹼性者“載入後馬上執行”這條軍規,所以,雖然它並不阻塞頁面渲染,但是你也無法控制他執行的次序和時機。
支援async
標籤的瀏覽器是:Firefox3.6+,Chrome8.0+,Safari5.0,IE10+。Opera還不支援參考這裡所以這個方法也不是太好。因此不是所有的瀏覽器你都能行。
動態建立DOM方式
這種方式可能是用的最多的了。
function loadjs(script_name){
var script = doucment.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', script_name);
script.setAttribute('id', 'my_script_id');
script_id = document.getElementById('my_script_id');
if(script_id){
document.getElementsByTagName('head')[0].removeChild(script_id);
}
document.getElementsByTagName('head')[0].appendChild(script);
};
var script = 'http://coolshell.cn/asyncjs/alert.js';
loadjs(script);
這個方式幾乎成了標準的非同步載入js檔案的方式。
按需非同步載入js
上面的那個DOM方式的例子解決了非同步載入javascript的問題,但是沒有解決我們想讓它按照我們指定的時機執行的問題。所以,我們只需要把上面的那個DOM方式幫到某個事件上來就可以了。
比如:
1) 綁在window.load 事件上(示例)
window.load = loadjs("http://coolshell.cn/asyncjs/alert.js")
2) 綁在特定的事件上(示例)
<p style="cursor: pointer" onclick="LoadJS()">Click to load alert.js </p>
比如當我們在點選某個DOM元素時,才載入我們的JS檔案。
更多
但是,繫結在某個特定事件上這個事似乎又過了點,因此只有在點選的時候才會去真正的下載js,這又會太慢了。,我們想要非同步地把嘉實穩鍵下載到本地,但又不執行,僅當在我們想要執行的時候去執行。
要是我們又下面的方式就好了:
var script = document.createElement("script");
script.noexecute = true;
script.src = "alert.js";
document.body.appendChild(script);
//後面我們可以這麼幹
script.execute();
可惜的是,這只是一個美麗的夢境,今天我們的javascript
還比較原始,這個js夢還沒有實現。
所以,我們的程式設計師只能是喲個hack的方式來搞。
有的程式設計師使用非標準的script的type來實現。如:
<script type=cache/script src="./alert.js"></script>
因為“cache/script
”,這個東西根本就不能被瀏覽器歇息,所以瀏覽器也就不能把alert.js
當javascript
執行,但是它又要去下載嘉實穩鍵,所以就可以搞定了。可惜的是,webkit
嚴格服從了HTML標準–對於這個不認識的東西,直接刪除,什麼也不幹,於是我們的夢又破了。
所以,我們需要在hack
以下,就是preload
圖片那樣,我們可以動用object
標籤(也可以使用iframe
標籤),於是我們有了下面這樣的程式碼:
function cachejs(script_filename){
var cache = document.createElement('object');
cache.data = script_filename;
cache.id = "coolshell_script_cache_id";
cache.width = 0;
cache.height = 0;
document.body.appendChild(cache);
}
在Chrome下按Ctrl+Shift+I。切換到network頁,你可以看到下載了alert.js
但是沒有執行,因為瀏覽器快取了,不會再從伺服器上下載alert.js
,所以,就能保證執行速度了。
最後在提兩個js,一個事ControlJs,另一個是HeadJs都是專門用來做非同步load javascript檔案的。
相關文章
- JavaScript 中的執行上下文和執行棧JavaScript
- 前端效能優化 --- css和js的裝載與執行前端優化CSSJS
- 《高效能JavaScript》讀書筆記①載入和執行JavaScript筆記
- [譯] 理解 JavaScript 中的執行上下文和執行棧JavaScript
- (譯文)JavaScript中的執行上下文和執行棧JavaScript
- JavaScript 編寫和執行方法JavaScript
- 【譯】理解 Javascript 執行上下文和執行棧JavaScript
- 瞭解Javascript中的執行上下文和執行堆疊JavaScript
- 前端-JavaScript作用域和執行分析前端JavaScript
- 深入理解 JavaScript 執行上下文和執行棧JavaScript
- 深入理解JavaScript執行上下文和執行棧JavaScript
- JavaScript中執行上下文和執行棧是什麼?JavaScript
- Kibana,Logstash 和 Cerebro 的安裝執行
- 前端效能優化:細說JavaScript的載入與執行前端優化JavaScript
- JavaScript的工作原理:引擎,執行時和呼叫堆疊JavaScript
- javascript引擎執行的過程的理解--執行階段JavaScript
- 【進階1-1期】理解JavaScript 中的執行上下文和執行棧JavaScript
- JavaScript執行環境與執行棧JavaScript
- 安裝ffmpeg和crontab執行ffmpeg
- JavaScript執行機制JavaScript
- Javascript 執行機制JavaScript
- 前端-JavaScript執行原理前端JavaScript
- 淺談Javascript單執行緒和事件迴圈JavaScript執行緒事件
- 【譯】JavaScript的工作原理:引擎,執行時和呼叫堆疊的概述JavaScript
- JavaScript是如何工作的:引擎,執行時和呼叫堆疊的概述!JavaScript
- JavaScript的程式碼執行機制JavaScript
- Javascript中new的執行過程JavaScript
- JavaScript中的執行上下文和堆疊是什麼JavaScript
- 聊一聊JavaScript中的執行上下文和堆疊JavaScript
- 【譯】JavaScript如何工作的:一覽引擎、執行時和呼叫棧JavaScript
- 1-1 JavaScript執行環境 執行棧JavaScript
- 解讀 JavaScript 之引擎、執行時和堆疊呼叫JavaScript
- JavaScript程式碼執行順序和資料型別JavaScript資料型別
- JavaScript執行原理解析JavaScript
- JavaScript單執行緒概念JavaScript執行緒
- JavaScript執行順序分析JavaScript
- 探索JavaScript執行機制JavaScript
- Selenium執行JavaScript指令碼JavaScript指令碼