Debounce in Javascript



我目前正在学习Javascript中的debounce,我遇到了两种编写debounce函数的方法,它们的工作原理是一样的。一个是简单得多的普通函数,另一个是复杂的,似乎每个人都在使用。

版本1:

@index.html

<input type="text" oninput="betterFunction()">

@script.js

function getData() {
console.log('Data Fetched')
}
function debounce(callback, delay) {
let timer
return function() {
clearTimeout(timer)
timer = setTimeout(() => {
callback();
}, delay)
}
}
const betterFunction = debounce(getData, 1000)

版本2:

@index.html

<input type="text" oninput="debounce()">

@script.js

let timer
function debounce() {
clearTimeout(timer)
timer = setTimeout(() => {
console.log('Data Fetched');
}, 1000)
}

如果这两种方式给出相同的结果,它们之间的区别是什么?PS:我很惊讶,我从来没有见过任何人使用"版本2",当然一定是我错了。有人能解释一下它们的区别吗?

版本1更好,因为它:

  • timer(超时ID)封装在函数调用
  • 的生存期范围内。
  • 消除了可能在其他函数外部或内部被意外修改的讨厌的全局变量
  • 最重要的是,它是可重复使用的

一个更好的脱线

Josh W Comeau有一篇关于debounce的翔实文章。

这是他的(修改的)最小版本:

const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback(...args);
}, wait);
};
}

注意:我将callback.apply(null, args)替换为更简洁的callback(...args)

使用

const handleMouseMove = debounce((mouseEvent) => {
// Do stuff with the event!
}, 250);
document.addEventListener('mousemove', handleMouseMove);    // Add listener
document.removeEventListener('mousemove', handleMouseMove); // Remove listener

片段在下面的代码片段中,每次用户在250ms后停止移动鼠标时都会绘制点。每个点在2秒后自动移除。

const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback(...args);
}, wait);
};
}
const createPoint = (x, y, color) => {
const point = Object.assign(document.createElement('div'), { className: 'point' });
Object.assign(point.style, { top: `${y - 2}px`, left: `${x - 2}px`, background: color });
document.body.append(point);
return point;
};
// Log mouse coordinates when user stops moving mouse after 250ms
const handleMouseMove = debounce(({ clientX: x, clientY: y }) => {
console.log(`Creating MOVE point at: (${x}, ${y})`);
const point = createPoint(x, y, 'white');
// Auto-remove after 1 second
setTimeout(() => {
console.log(`Removing MOVE point at: (${x}, ${y})`);
point.remove();
}, 2000);
}, 250);
// Log mouse coordinates when user stops clicking 250ms
const handleClick = debounce(({ clientX: x, clientY: y }) => {
console.log(`Creating CLICK point at: (${x}, ${y})`);
const point = createPoint(x, y, 'red');
// Auto-remove after 1 second
setTimeout(() => {
console.log(`Removing CLICK point at: (${x}, ${y})`);
point.remove();
}, 2000);
}, 250);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('click', handleClick);
.as-console-wrapper { max-height: 5em !important; }
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { background: #222; position: relative; }
.point { position: absolute; width: 4px; height: 4px; border-radius: 50%; background: #FFF; }

Debounce function是一个用于延迟函数执行的javascript编程模式,您的版本1是实现Debounce特性的普遍接受模式,因为它比版本2更好,原因由MR. Polywhirl列出。

该模式实际上利用了一个称为closure的javascript特性,它允许内部函数(由debounce返回的函数)访问它们的外部作用域(特别是在本例中,声明的变量timer)。

您可以在这里详细阅读关于闭包的内容,以进一步理解为什么版本1是首选版本,但是这个闭包的解释/示例可能一开始更容易掌握。

相关内容

  • 没有找到相关文章

最新更新