防抖:在任务高频率触发时,只有触发间隔超过制定间隔的任务才会执行。即一个动作连续触发则只执行最后一次。防抖的原理则是不管你在一段时间内如何不停的触发事件,只要设置了防抖,则只在触发n秒后才执行。如果我们在一个事件触发的n秒内又触发了相同的事件,那我们便以新的事件时间为标准,n秒之后再执行。
let timer = flase;
document.addEventListener('scroll', function() {
clearTimeout(timer); // 清除未执行的定时器(如果之前已经触发过不到300毫秒又触发了一次则清除之前的)重置回初始化状态
timer = setTimeout(function(){
console.log("函数防抖")
}, 300)
})
节流:在制定间隔内任务只执行1次。节流的原理是不管你在一段时间内如何不停地触发事件,只要设置了节流,就会每隔一段时间执行一次。
let canRun = true;
document.addEventListener('scroll', function() {
if (!canRun) return;
canRun = false;
setTimeout(function(){
console.log('函数节流')
canRun = true
}, 300)
})
两者区别:一定时间内任务执行的次数。防抖是只执行重复操作的最后一次,而节流是每多少单位时间内只执行一次。一个在线体验防抖和节流的效果的网站:http://demo.nimius.net/debounce_throttle/
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
形象记忆
防抖:假设电梯的安全机制为每人进门后1分钟(wait)后才有关门动作,你第一个进电梯,快50秒的时候进来一位乘客(触发deBounce),得,刚才的50秒白等啦(clearTimeout),两人得一起重来再等新的1分钟。刚过又30秒,上来另一位乘客(再次触发deBounce),关门指令定时器又作废了(clearTimeout),大家得重新等新的1分钟,这1分钟内没人进来(触发deBounce)的话,那1分钟后关门动作就会执行了。
封装防抖函数:
function deBounce(fn, wait) {
var timer
return function() {
if(timer) { clearTimeout(timer) }
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
}
要点:如果在定时器的时间范围内再次触发,则重新计时。
效果见:https://jsbin.com/hufazicemu/edit?html,console,output
节流:假设近期我们有发放口罩 的爱心机制——每天早上8点发一个,必须一天后口罩寿命到了戴完用掉了才能再来领新的。24h内(wait)没用完丢弃前,你来领口罩(触发throttle)是不能给你发放的,你反复几次来领都没用,看到你口罩还能用(timer为真)就劝退(不执行if语句)。等24h时间到了后(setTimeout宏任务执行)口罩戴完了扔掉了(timer = null),看到你脸上没口罩可用了(timer为假),就才执行发放口罩动作(if语句内动作)。
封装节流函数:
function throttle(fn, wait) {
var timer
return function() {
if (!timer) {
timer = setTimeout(() => {
timer = null
fn.apply(this, arguments)
}, wait)
}
}
}
效果:https://jsbin.com/vevamuwusa/edit?html,console,output
另一种写法(原理相同):
function throttle(fn, interval) {
let canRun = true
return function(){
if(!canRun) {
return
}
canRun = false
setTimeout(()=>{
fn.apply(this, arguments)
canRun = true
}, interval)
}
}
要点:如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器。
效果见:https://jsbin.com/yuruzoravi/1/edit?html,console,output
本文参考:
第 3 题:什么是防抖和节流?有什么区别?如何实现? | 木易杨前端进阶 muyiy.cn/question/js/3.html 高效前端:Web高效编程与优化实践 book.douban.com/subject/30170670/ 函数节流和函数防抖 · 语雀 www.yuque.com/jimmie/web-developer/nb0ntl 22 防抖节流背后那些事儿-慕课专栏 www.imooc.com/read/41/article/635