返回課程

延遲裝飾器

重要性:5

建立一個裝飾器 delay(f, ms),它會延遲 f 的每個呼叫 ms 毫秒。

例如

function f(x) {
  alert(x);
}

// create wrappers
let f1000 = delay(f, 1000);
let f1500 = delay(f, 1500);

f1000("test"); // shows "test" after 1000ms
f1500("test"); // shows "test" after 1500ms

換句話說,delay(f, ms) 會傳回一個「延遲 ms」的 f 變體。

在上述程式碼中,f 是單一參數的函式,但您的解答應該傳遞所有參數和內容 this

開啟一個有測試的沙盒。

解答

function delay(f, ms) {

  return function() {
    setTimeout(() => f.apply(this, arguments), ms);
  };

}

let f1000 = delay(alert, 1000);

f1000("test"); // shows "test" after 1000ms

請注意這裡是如何使用箭頭函式的。我們知道,箭頭函式沒有自己的 thisarguments,所以 f.apply(this, arguments) 從包裝器取得 thisarguments

如果我們傳遞一個常規函式,setTimeout 會在沒有參數和 this=window 的情況下呼叫它(假設我們在瀏覽器中)。

我們仍然可以使用中間變數傳遞正確的 this,但那會稍微麻煩一點

function delay(f, ms) {

  return function(...args) {
    let savedThis = this; // store this into an intermediate variable
    setTimeout(function() {
      f.apply(savedThis, args); // use it here
    }, ms);
  };

}

在沙盒中開啟有測試的解答。