节流:在规定时间段内只执行一次
防抖:在执行函数时候,在一定时间后再触发回调函数,如果函数再次执行,则重新计时
目的是为了优化高频事件导致浏览器崩溃,并且降低 CPU 和内存的消耗,减轻服务器请求的压力,并且优化用户体验
实现原理
节流 throttle
- 设定一个固定的时间间隔 delay
- 记录上次触发的时间
- 每次事件触发,检查当前时间
- 如果当前时间-上次时间>=delay 的时间戳,则执行回调
实现:
function throttle(func, delay) {
let lastTime = 0;
return function (...args) {
const context = this;
const nowTime = Date.now();
if (nowTime - lastTime >= delay) {
lastTime = nowTime;
func().apply(context, [...args]);
}
};
}
window.addEventListener(
"scroll",
throttle(() => {
// 需要节流控制的触发事件
console.log("需要节流的事件触发");
}, 2000)
);防抖 debounce
- 也需要设定一个延迟时间 delay
- 然后创建一个延时执行变量 let timer= null;
- 先判断是否存在 timer,如果存在说明上一个 timer 还没执行并销毁,则先销毁 timer 指向的定时器,将 timer = null;
- 然后重新创建一个新的延时为 delay ,执行事件为传入需要延时执行的方法的定时器
实现:
function debounce(func,delay){
let timer = null;
return function(...args){
// 由于setTimeout里面this会指向setTimeout返回的对象,
// 所以这里使用context保存一下当前匿名函数的this指向
const context = this;
if(timer) clearTimeout(timer);
timer = setTimeout(()=>{
func.apply(context,args);
},delay);
};
}
// 调用
document.getElementById("myinput").addEventListener(
"input",
debounce((e) => {
console.log("输入停止:", e.target.value);
}, 500)
);对比
节流:
- 固定频率执行
- 至少保证一定时间内一定要执行一次
- 场景:适合高频响应的事件
- 滚定加载 scroll
- 搜索框实时建议(输入频率很高,但需要周期检查),例子:百度搜索栏下面弹出的建议
- 监听浏览器窗口变化(resize)
- 游戏中的射击按钮
防抖:
- 事件停止后执行
- 保证一段空闲时间后才执行一次
- 场景:需要在事件停止一段时间后再执行操作的场景
- 搜索框输入:用户停止输入再获取值
- 窗口大小修改:窗口停止拖动再渲染
- 拖拽事件 dragend