首先看一個例子:
function foo() {
console.log('first');
setTimeout((function(){
console.log('second');
}),5);
}
for(var i =0;i<10000;i++) {
foo();
}
結果是先輸出10000個first然後立即輸出10000個second。
因爲JavaScript是單線程運行的,特定的時間只能有特定的代碼正在執行,不會有多段代碼同時執行。
setTimeout一般文檔中的描述是一段時間後執行某段代碼或者方法,但是嚴格說來不是的,應該是一段時間後把某段代碼或者方法放入執行隊列中,至於什麼時候能執行它們就只能等JavaScript引擎按照隊列一個一個進行。
上面的例子,setTimeout中的方法只能等待for循環結束後才執行,因爲for循環在執行隊列中靠前。
但是瀏覽器卻不是單線程的,一個瀏覽器可能有以下進程:javascript引擎線程、界面渲染線程、瀏覽器事件觸發線程、Http請求線程。而且瀏覽器依靠事件驅動機制來確定代碼的執行隊列。
所以就不難理解爲什麼AJAX是異步操作的了。
由於JavaScript是單線程的,所以儘管瀏覽器可以並行下載js文件,但是也必須依次順序下載。
實現非阻塞的js文件下載有兩種方法:
1. HTML5的defer和async。
<script type="text/javascript" defer src="foo.js"></script>
<script type="text/javascript" async src="foo.js"></script>
2. 動態加載js文件
var script=document.createElement('script');
script.setAttribute("type","text/javascript");
script.setAttribute("src","xxx.js");
document.documentElement.appendChild(script);
//or: document.getElementsByTagName('head')[0].appendChild(script);
//or: document.body.appendChild(script);