JavaScript 中的去抖动

Voo*_*ild 3 javascript debouncing

我目前正在学习 Javascript 中的去抖动,并且遇到了两种编写工作原理相同的去抖动函数的方法。一种是像常规函数一样简单的函数,另一种是每个人似乎都使用的复杂函数。

版本1:

@index.html

<input type="text" oninput="betterFunction()">
Run Code Online (Sandbox Code Playgroud)

@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)
Run Code Online (Sandbox Code Playgroud)


版本2:

@index.html

<input type="text" oninput="debounce()">
Run Code Online (Sandbox Code Playgroud)

@script.js

let timer

function debounce() {
  clearTimeout(timer)
  timer = setTimeout(() => {
    console.log('Data Fetched');
  }, 1000)
}
Run Code Online (Sandbox Code Playgroud)

如果这两种去抖方法都给出相同的结果,那么它们之间有什么区别?PS:令我惊讶的是我从未见过有人使用“版本2”,当然我一定是错了。有人可以解释一下这些差异吗?

Mr.*_*irl 10

版本 1 更好,因为它:

\n
    \n
  • 将(超时ID)封装timer在\xe2\x80\x94范围内\xe2\x80\x94函数调用的生命周期内
  • \n
  • 消除了可能在另一个函数外部或内部意外修改的讨厌的全局变量
  • \n
  • 最重要的是,它是可重复使用的
  • \n
\n

更好的防抖

\n

Josh W Comeau有一篇内容丰富的文章,介绍了反跳。

\n

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

\n
const debounce = (callback, wait) => {\n  let timeoutId = null;\n  return (...args) => {\n    window.clearTimeout(timeoutId);\n    timeoutId = window.setTimeout(() => {\n      callback(...args);\n    }, wait);\n  };\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

用法

\n
const handleMouseMove = debounce((mouseEvent) => {\n  // Do stuff with the event!\n}, 250);\n\ndocument.addEventListener(\'mousemove\', handleMouseMove);    // Add listener\ndocument.removeEventListener(\'mousemove\', handleMouseMove); // Remove listener\n
Run Code Online (Sandbox Code Playgroud)\n

片段

\n

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

\n

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

\n