Github 代码:github.com/Haixiang612…预览:yanhaixiang.com/debounce-th…
debounce 和 throttle 是面试时经常会被问到的一道 JS 题。我自己在第一次找工作的时候,就被问过。当时被问得半天说不出两者的区别,说着说着就把自己带入坑了。
今天就跟大家分享一下这两者的区别吧。
debounce 是什么
中文名:防抖。在开始操作了之后,那么只有在一段 delay 时间段后不再有操作了,才执行操作。
const onClick = debounce(fn, 300) click // 不执行 fn click // 不执行 fn 等 200 ms 后再 click // 不执行 fn 等 500 ms 后再 click // 执行 fn 复制代码
相信大家上初中物理都见过音叉
当有东西碰到它的时候,就会一直在震,防抖可以形象地理解为:当不再震动的时候做一些事情。
最常见的场景就是用户不断点击“提交”按钮,debounce 生成的函数就可以在用户一段时间内不再点击时,再执行“提交”操作。
debounce 实现
实现思路如下:
- setTimeout 在 delay ms 后执行
- 每次调用 debounced 函数时,都直接清除掉 timerId
- 当一段时间过去了(大于 delay ms),setTimeout 就会自动执行 fn
function debounce(fn, delay) { let timerId, context, args function debounced() { [context, args] = [this, arguments] clearTimeout(timerId) // 以后再次调用的时候会清除掉 timerId = setTimeout(() => { fn.apply(context, arguments) // 到点执行 }, delay) } return debounced } 复制代码
throttle 是什么
中文名:节流。在开始操作之后,在 delay ms 内只会做一次。
const onMove = throttle(fn, 300) move // 第一次先执行 move // 300 ms 后执行 fn 过了 3 ms 后 move // 准备在 303 ms 执行 fn 过了 100 ms 后 move // 将上一次的 timerId 去掉,准备 400 ms 执行 fn 过了 301 ms 后 move // 马上执行 fn 复制代码
节流,字面意思就可以理解为 threshold ms 一段时间里做一件事,类似于技能的 CD。当然,这么来理解可能不太准确的,因为 throttle 还有一个条件就是最多执行一次。比如,在 CD 值冷却的时候去执行,虽然现在执行不了,但是会在 delay ms 执行。
只有在无限多次执行上面的 move 才会出现 threshold ms 后再执行一次的技能 CD 效果。
throttle 实现
实现思路如下:
- 第一次调用的时候就执行了
- 当上一次时间 + threshold > 当前时间(CD 值在冷却)时调用,会在 thresold ms 后执行
- 执行 fn 时会记录当前时间为 preivous
function throttle(fn, threshold) { let timerId, previous function throttled() { let [context, args] = [this, arguments] const now = Date.now() // 记录当前时间 if (previous && now < previous + threshold) { clearTimeout(timerId) // 以后调用时,清除时间 timerId = setTimeout(() => { // 重新计时 previous = now // 记录时间用于以后的比较 fn.apply(context, args) }, threshold) } else { previous = now //记录时间用于以后的比较,开始一段新的时间段 fn.apply(context, args) } } return throttled }