共计 2545 个字符,预计需要花费 7 分钟才能阅读完成。
防抖和节流都是闭包的利用,先了解闭包,再了解防抖和节流
防抖(debounce)
先不说概念,按本人的了解,在单反里,有防抖机制。因为人在拿着单反的时候会手抖(单反重),按下快门的霎时,照片会糊,所以有防抖机制,以避免老手把照片拍糊
单反中的防抖是避免抖动,让人拍出清晰的照片,JavaScript 中的防抖是为了什么?
同理,它的作用也是避免抖动。试想当你频繁触发一个事件时,就会引起不必要的性能损失,那么让该事件在进行触发后再触发,以此缩小局部性能
防抖的定义
防抖就是要提早执行,你始终操作触发事件始终不执行,当你进行操作期待多少秒后才执行
也就是说不论事件触发频率有多高,肯定在事件触发 n 秒后执行。如果在事件触发的 n 秒又触发了这个事件,那就以新事件的事件为准,n 秒后才执行。总之,要等你触发完事件 n 秒内不再触发事件,它才执行
手写防抖
依据定义,咱们晓得要在工夫 n 秒后执行,那么咱们就用定时器来实现
function debounce(event, wait) {
let timer = null;
return function (...args) {clearTimeout(timer); // 革除 setTimeout,使其回调函数不执行
timer = setTimeout(() => {event.apply(this, args);
}, wait);
};
}
代码很简略,即当还在触发事件时,就革除 timer,使其在 n 秒后执行,但此写法首次不会立刻执行,为其健壮性,需加上判断是否第一次执行的第三个参数 flag,判断其是否立刻执行
function debounce(event, wait, flag) {
let timer = null;
return function (...args) {clearTimeout(timer);
if (!timer && flag) {event.apply(this, args);
} else {timer = setTimeout(() => {event.apply(this, args);
}, wait);
}
};
}
防抖场景
窗口大小变动,调整款式
window.addEventListener('resize', debounce(handleResize, 200));
搜寻框,输出后 1000 毫秒搜寻
debounce(fetchSelectData, 300);
表单验证,输出 1000 毫秒后验证
debounce(validator, 1000);
防抖帝王库
两大工具库都有防抖源码,可供参考
lodash-debounce
underscore-debounce
节流(throttle)
顾名思义,一节一节的流,就好似管制水阀,在事件一直触发的过程中,固定工夫内执行一次事件
手写节流
因为是固定工夫内执行一次工夫,所以咱们有两种实现办法,一用工夫戳,二用定时器
工夫戳
function throttle(event, wait) {
let pre = 0;
return function (...args) {if (new Date() - pre > wait) {
// 当 n 秒内不反复执行
pre = new Date();
event.apply(this, args);
}
};
}
应用工夫戳尽管能实现节流,然而最初一次事件不会执行
定时器
function throttle(event, wait) {
let timer = null;
return function (...args) {if (!timer) {timer = setTimeout(() => {
timer = null;
event.apply(this, args);
}, wait);
}
};
}
应用定时器实现节流,尽管最初一次能触发,然而第一次不会触发
工夫戳 + 定时器
为解决第一次和最初一次都能够触发,把两者联合起来
function throttle(event, wait) {
let pre = 0,
timer = null;
return function (...args) {if (new Date() - pre > wait) {clearTimeout(timer);
timer = null;
pre = new Date();
event.apply(this, args);
} else {timer = setTimeout(() => {event.apply(this, args);
}, wait);
}
};
}
节流场景
scroll 滚动
window.addEventListener('scroll', throttle(handleScroll, 200));
input 动静搜寻
throttle(fetchInput, 300);
节流帝王库
lodash-throttle
underscore-throttle
总结
防抖:只执行最初一次。事件继续触发,但只有等事件进行触发后 n 秒后才执行函数
节流:管制执行频率。继续触发,每 n 秒执行一次函数
比照图:
线上 demo(司徒正美的 demo):防抖节流
参考资料
- awesome-coding-js
- 防抖节流场景及利用
- 函数防抖与函数节流
系列文章
- 深刻了解 JavaScript——开篇
- 深刻了解 JavaScript——JavaScript 是什么
- 深刻了解 JavaScript——JavaScript 由什么组成
- 深刻了解 JavaScript——所有皆对象
- 深刻了解 JavaScript——Object(对象)
- 深刻了解 JavaScript——new 做了什么
- 深刻了解 JavaScript——Object.create
- 深刻了解 JavaScript——拷贝的机密
- 深刻了解 JavaScript——原型
- 深刻了解 JavaScript——继承
- 深刻了解 JavaScript——JavaScript 中的始皇
- 深刻了解 JavaScript——instanceof——找祖籍
- 深刻了解 JavaScript——Function
- 深刻了解 JavaScript——作用域
- 深刻了解 JavaScript——this 关键字
- 深刻了解 JavaScript——call、apply、bind 三大将
- 深刻了解 JavaScript——立刻执行函数(IIFE)
- 深刻了解 JavaScript——词法环境
- 深刻了解 JavaScript——执行上下文与调用栈
- 深刻了解 JavaScript——作用域 VS 执行上下文
- 深刻了解 JavaScript——闭包