setTimeout(func,0)第二個引數為0分析

admin發表於2018-08-20

在很多實際專案中,會有如下類似程式碼:

[JavaScript] 純文字檢視 複製程式碼
setTimeout(func,0)

看上去比較怪異,為何要等著0秒以後再去執行func函式,而不是直接呼叫。

可能不少初學者和當年本人一樣,甚至會生出這樣的想法,是不是專案人員在裝逼或者故弄玄虛。

出現上述想法,基本是因為對於如下兩個方法和概念沒有理解透徹:

(1).setTimeout()方法一章節。

(2).JavaScript非同步詳解一章節。

首先看一段程式碼例項:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
for (var index = 1; index <= 3; index++) {
  setTimeout(function(){
    console.log(index);
  },0);  
};

在直觀上,列印結果應該是1,2,3,但是實際列印結果是4,4,4

結果分析如下:

即便第二個引數為0,setTimeout方法依然具有非同步功能,又由於JavaScript是單執行緒,所以setTimeout回撥函式只能在佇列中排隊,等待for迴圈執行完畢,這時index值已經變成4,所以列印結果都是4。

再來看一段例項程式碼加深與上述程式碼的理解:

[JavaScript] 純文字檢視 複製程式碼
function onReady(fn) {
  var readyState = document.readyState;
  if (readyState ==="interactive" || readyState === "complete") {
    fn();
  } else {
    window.addEventListener("DOMContentLoaded", fn);
  }
}
onReady(function () {
  console.log("DOM結構載入完畢");
});
console.log("開始輸出:");

上述程式碼本意要實現,當文件結構完全載入完畢再去執行onReady的回撥函式。

但是程式碼有一個問題,程式碼會根據DOM載入的狀態,輸出結果也會不同。

如果DOM結構未載入完畢,以非同步的方式執行fn,如果DOM結構已經載入完畢,以同步的方式執行fn。

載入完畢輸出順序:

(1)."DOM結構載入完畢"。

(2)."開始輸出"。

未載入完畢輸出順序:

(1)."開始輸出"。

(2)."DOM結構載入完畢"。

所以要防止上面問題的出現,統一做非同步處理,程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼
function onReady(fn) {
  var readyState = document.readyState;
  if (readyState ==="interactive" || readyState === "complete") {
    setTimeout(fn, 0);
  } else {
    window.addEventListener("DOMContentLoaded", fn);
  }
}
onReady(function () {
  console.log("DOM結構載入完畢");
});
console.log("開始輸出:");

上面程式碼通過setTimeout(fn, 0)方式巧妙解決所存在的問題。

相關文章