JavaScript Debounce - одинаково ли работают эти функции?
Искал решения для debounce-функции в js и нашёл этот вариант:
function debounce1(func, ms) {
let timeout;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, arguments), ms);
};
}
Затем поэкспериментировал со способом вызова функции в setTimeout и получились эти два варианта, которые, кажется, работают также.
Есть ли отличия в работе этих функций?
// с ...args
function debounce2(func, ms) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), ms);
};
}
// с arguments
function debounce3(func, ms) {
let timeout;
return function () {
clearTimeout(timeout);
timeout = setTimeout(func, ms, ...arguments);
};
}
Ответы (2 шт):
Для начала
Дополню ваш вопрос ещё 1 вариантом. Рассмотрим как работают следующие 4 функции:
function print(p1) {
console.log(this, [...arguments]);
}
function debounce1(func, ms) {
let timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, arguments), ms);
};
}
function debounce2(func, ms) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), ms);
};
}
function debounce3(func, ms) {
let timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(func, ms, ...arguments);
};
}
function debounce4(func, ms) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func, ms, ...args);
};
}
debounce1(print, 0)(1);
debounce2(print, 0)(1);
debounce3(print, 0)(1);
debounce4(print, 0)(1);
Получим результат:
undefined, [0]
undefined, [0]
window, [0]
window, [0]
Вывод - у первой пары this отсутствует, а у второй ссылается на window.
Теперь рассмотрим по-подробнее.
Анализ
Отметим, что this и arguments ссылаются на анонимную функцию.
- У функции нету
this- отсюда иundefinedв функции 1 и 2. - Передавать аргументы в массив или получить с помощью
argumentsособого разницы нет. Поэтому у всех одинаковые аргументы. НО! Не советую использоватьarguments. Запрещена в строгих контекстах (там, где использовано"use strict")
Да и не советуют. Вот заметка на MDN:
- И почему же мы получаем
windowв 3 и 4 функциях? Дело в том, что у функции переданного вsetTimeoutпереписываетсяthisнаwindow. Проверить можем следующим кодом:
function print() {
console.log(this);
}
print(); // undefined
setTimeout(print); // window
Результат
И почему же я добавил 4-ий вариант?
Потому что я советую именно его. В нем не используется arguments и в него передаюся значения как это задумано по setTimeout.
debounce2 лучший вариант
// с ...args
function debounce2(func, ms) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), ms);
};
}