概念
节流 throttle:n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效。
减少一段时间的触发频率。
- 场景:scroll
防抖 debounce:n 秒再在执行该事件,若在 n 秒内被重复触发,则重新计时。
在一定的时间间隔内,将多次触发变成一次触发。
- 场景:resize
可视化演示:http://demo.nimius.net/debounce_throttle/
注意event参数
document.getElementById("app").addEventListener("click",test);
function test(e){
console.log(this);//<div id=app></div> dom对象
console.log(e) //Event对象
}
// addEventListener(event, function, useCapture) 中的 function 回调函数,默认一个参数为event
// https://wonderlust91.github.io/2018/12/06/javascript%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%8F%82%E6%95%B0/
节流throttle
https://code.h5jun.com/letab/edit?html,js,console,output
//🔥时间戳,缺点:第一次会执行,最后少一次
function throttle1(fn, timeout) {
let last = 0;
return function () {
let now = Date.now();
if (now - last >= timeout) {
last = now;
fn.apply(this, arguments); // this是dom,args 第一个是event事件
}
};
}
//🔥定时器,缺点:最后一次也会等一个时间间隔
function throttle2(fn, timeout) {
let timer = null;
return function () {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, timeout);
}
};
}
// 结合
function throttle3(fn, timeout) {
let timer = null;
let last = 0;
return function () {
let now = Date.now();
let remaining = timeout - (now - last);
if (remaining <= 0) {
fn.apply(this, arguments);
last = now;
} else if(!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments);
last = Date.now();
timer = null
}, remaining);
}
};
}
防抖debounce
//🔥初级版本 第一次执行延时
function debounce1(fn,wait){
let timer = null;
return function(){
if(timer){
clearTimeout(timer);
}
timer=setTimeout(()=>{
fn.apply(this, arguments);
},wait);
}
}
// 🔥反过来 第一次执行
function debounce2(fn, timeout) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
if (!timer) {
fn.apply(this, arguments);
}
timer = setTimeout(() => {
timer = null;
}, timeout);
};
}
参考: 【爪哇教育 2021大厂前端核心面试题详解-路白-哔哩哔哩】https://b23.tv/2CRSnh https://www.bilibili.com/video/BV1Vy4y1y7tj?p=2 https://segmentfault.com/a/1190000017227559 https://github.com/mqyqingfeng/Blog/issues/26 https://www.zoo.team/article/anti-shake-throttle