一个经典的比喻:
想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应
假设电梯有两种运行策略 debounce 和 throttle,超时设定为15秒,不考虑容量限制
电梯第一个人进来后,15秒后准时运送一次,这是节流
电梯里第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖
首选,给出总结:
相同点
都可以通过使用 setTimeout 实现
降低回调执行频率。节省计算资源
不同点
函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
函数节流,不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数
防抖只是在最后一次事件后才触发一次函数。
应用场景
例如,都设置时间频率为500ms,在2秒时间内,频繁触发函数,节流,每隔 500ms 就执行一次。防抖,则不管调动多少次方法,在2s后,只会执行一次
防抖应用场景:
搜索框输入查询、手机号、邮箱验证输入检测。只需用户最后一次输入完,再发送请求
窗口大小resize。只需窗口调整完成后,计算窗口大小,防止重复渲染。
节流应用场景:
监听滚动事件判断是否到页面底部自动加载更多
搜索联想功能
DOM元素的拖拽功能实现
射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
防止高频点击提交,防止表单重复提交;
以输入框查询功能为例:
//html:
<span>查询:</span>
<input type="text" id="inputVal">
//js:
//未处理
$(document).on("keyup","#inputVal",function(){
//执行内容
console.log($("#inputVal").val());
})
//防抖处理
var timer=null;
$(document).on("keyup","#inputVal",function(){
if(timer){//在执行中 (如果之前的定时器还存在,则清除)
clearTimeout(timer);
}
//500ms后再触发
timer=setTimeout(function(){
//执行内容
console.log($("#inputVal").val());
timer=null;//本次查询完成,定时器清除,以便下次查询处理
}, 500);
})
防抖函数封装:
//fn为事件处理函数 delay延迟时间
function debounce(fn, delay) {
var timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments); //this和参数
timer = null;
}, delay);
};
}
以滚动页面到底部为例:
添加节流处理后的效果:scroll事件中的代码,会在事件触发时,每隔500ms触发一次。
//未处理
var i=0;
window.onscroll=function(){
console.log(++i);
var scrollTop=document.documentElement.scrollTop;
var clientHeight=document.documentElement.clientHeight;
var scrollHeight=document.documentElement.scrollHeight;
var scrollHeight=document.documentElement.scrollHeight;
if(scrollTop+clientHeight>=scrollHeight){
console.log('到底了!');
}
}
//防抖处理
var i=0;
var timer=null;
window.onscroll=function(){
if(timer){
return;
}
timer=setTimeout(function(){
console.log(++i);
var scrollTop=document.documentElement.scrollTop;
var clientHeight=document.documentElement.clientHeight;
var scrollHeight=document.documentElement.scrollHeight;
var scrollHeight=document.documentElement.scrollHeight;
if(scrollTop+clientHeight>=scrollHeight){
console.log('到底了!');
}
timer=null;
},500)
}
节流函数封装:
//节流封装
function throttle(fn, delay) {
var timer = null;
return function () {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(this, arguments);//把this和参数传递过去
timer = null;
}, delay);
};
}
参考:
https://baijiahao.baidu.com/s?id=1752769417074179461&wfr=spider&for=pc
https://baijiahao.baidu.com/s?id=1738733742087151995&wfr=spider&for=pc