首先看看下面的程式碼,會發現永遠跑不出So sad
,因為Javascript為單線程
,雖然設定1秒過後isEnd為false,然後應該就直接跑出So sad
,但因為被while一直佔住線程,因此永遠不會執行setTimeout事件,與console.log(“So sad”) 。
setTimeout(function () {
isEnd = false;
}, 1000);
while (isEnd);
console.log("So sad");
Javascript的單線程是指一個瀏覽器行程(process)只有一個JS的執行線程(但不代表瀏覽器是單線程),同一個時段內只會有一段代碼在執行,代表一次只能完成一件事,如果有多件事,就代表你要排隊,一件一件的處理,如果有一件事卡死或要做很久,就代表下面的事永遠不會執行,優點是簡單,環境單純,但缺點是如果其中一個事件很耗時間,會拖慢整個程式執行。
Javascript將事件分為兩種同步(Synchronous)
與非同步(Asynchronous)
來解決單線程的缺點。
同步( Synchronous )
就是一個完成換下一個,下一個完再換下下一個處理,程式執行順序與任務的排列順序是相同的,如下程式碼。
console.log(1);
console.log(2);
console.log(3);
輸出結果。
1
2
3
非同步( Asynchronous )
非同步為每一個任務都有一個CallBack
,代表每個任務執行完後會執行該CallBack
而不是執行下一個任務,因此程式執行順序與任務的排列順序是不相同的,下列以ajax為範例。
console.log(1);
$.ajax({
url:"tests/1"
success:function(data){
console.log(2);
}
})
console.log(3);
輸出結果。
1
3
2
也就是說,假設該ajax很耗時,你可以不用等到ajax執行完,才跑console.log(3)
,而是先給它個callback等ajax執完後自動插入回線程中執行console.log(2)
。
為什麼 Javascript 是單線程 ?
Javascript
最初做為瀏覽器腳本語言,主要用途在於和使用者戶動與操作DOM,也因此如果該語言為多線程語言就會發生不少混亂,例如Javascript
有兩個線程,一個線程針對某個DOM節點新增某些內容,而另一線程為刪除該節點,那瀏覽器要以那個為主?所以為了避免這些亂,因此Javascript
被設計為單線程語言。
HTML5提出了Web Worker的標準,web worker是運行在瀏覽器的後台,並且子線程完全由主線程控制,並且不得操作
DOM,所以該標準並沒有影響javascript為單線程的本質。
Javascript 為單線程,又怎著非同步的執行呢 ?
通常這種語言為單線程,但又可以處理非同步的語言都有個一種共同點,那就是事件驅動event driven)機制
,一般是由通過事件循環(Event Loop)
與事件隊列(Event Queue)
來實現。