Delaying decorator
Create a decorator delay(f, ms) that delays each call of f by ms milliseconds.
For instance:
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
In other words, delay(f, ms) returns a “delayed by ms” variant of f.
In the code above, f is a function of a single argument, but your solution should pass all arguments and the context this.
The solution:
function delay(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
let f1000 = delay(alert, 1000);
f1000("test"); // shows "test" after 1000ms
Please note how an arrow function is used here. As we know, arrow functions do not have own this and arguments, so f.apply(this, arguments) takes this and arguments from the wrapper.
If we pass a regular function, setTimeout would call it without arguments and this=window (assuming we’re in the browser).
We still can pass the right this by using an intermediate variable, but that’s a little bit more cumbersome:
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);
};
}