对于防抖和节流的理解
场景
日常开发过程中,很多地方能使用到防抖函数,和节流函数。二者都有一个共同的目的降低函数的执行次数,常见的场景有
- 防抖
- 对用户输入的关键字实时检索内容
- 鼠标不断点击触发,mousedown(单位时间内只触发一次) mousemove事件
- 用户操作内容的实时保存
- 节流
- scroll 事件
- 拖拽时,通过鼠标位置实时更新拖拽内容的坐标
防抖函数(debounce)
防抖顾名思义,防止疯狂抖动,第一次触发事件时,不立即执行函数,而是给出一个期限值比如 1s。
需求
- 如果在1s内没有在次触发事件,那就执行函数。
- 如果在1s内再次触发事件,则清除上一次的计时器,重新计时。
得到的结果就是: 如果在短时间内,多次触发事件,则只会执行一次
实现
每个函数维护的计时器都是独立的。闭包内的变量相互独立。
function debounce (fn, time) { // 入参为调用函数 和 间隔事件
let timer = null; // 储存定时器实例
return () => {
if (timer) { // 清除计时器
clearTimeout(timer)
}
timer = setTimeout(fn, time)
}
}
分析
- 若在time时间内触发,会执行clearTimeout 清除timer。重新设定一个新的timer。
- 若超过time在触发,那么time中的函数已经执行了。再次清除已经执行的timer,重新设定一个新的timer。
符合预期。
工具
lodash中已经实现了防抖函数,用法同上。
import { debounce } from 'lodash'
节流函数(throttle)
通过名称来记忆。理解为像流水一样连绵不断,像技能冷却时间一样。
防抖函数在某些场景下,存在长时间不触发的场景。比如我短时间内一直去触发事件,那么事件就一直不会被执行。
需求
- 函数执行后的一段时间内,函数失效。
// 普通函数版
function throttle (fn, time) { // 入参为调用函数 和 间隔事件
let firstTimer = Date.now()
return () => {
if (Date.now() - firstTimer > time) {
fn()
firstTimer = curentTimer
}
}
}
// setTimeout 版本
function throttle (fn, time) { // 入参为调用函数 和 间隔事件
let isrun = true
return () => {
if (!isrun) {
return
}
isrun = false
setTimeout(() => {
fn()
isrun = true
}, time)
}
}
分析
- 若在time时间内触发,不会立即执行。
- 若超过time在触发,会执行函数,并且计时器更新。
工具
lodash中已经实现了防抖函数,用法同上。
import { throttle } from 'lodash'

浙公网安备 33010602011771号