什么是防抖?什么是节流?手写一个
- n秒内只运行一次,若在n秒内重复触发,只有一次生效
if(timer){ return }
- 节流是限制函数在某段时间内只能执行一次,或者说每隔一段时间执行一次。
- 如果在指定的时间间隔内再次触发该事件,函数调用将被忽略,直到时间间隔过去后才会执行下一次调用。
- 其跟防抖的主要区别在于 保证了函数是有规律的执行,每xx毫秒执行一次。
- 节流适用于需要以固定的速率处理事件的情况,比如滚动事件、鼠标移动事件等。
- 节流函数的实现原理是
- 将即将被执行的函数用定时器延时一段时间后执行;
- 如果定时器还在,说明上次延迟执行还未完成,则忽略调用函数的请求(return);
- 节流函数接受两个参数,第一个是 需要被延时执行的函数,第二个是需要延迟的时间。
- 代码:
function throttle(fn, delay = 1000) {
let timer = null;
return function () {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
};
}
const dragdiv = document.getElementById('dragdiv');
dragdiv.addEventListener(
'drag',
throttle(function (e) {
console.log(e.offsetX, e.offsetY);
})
);
- n秒后再执行该事件,若在n秒内被重复触发,则重新计时
if(timer){ clearTimeout(timer) }
- 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次;
- 如果设定的时间到来之前,又一次触发了事件,就重新开始延时;
- 可以理解为多个相同的事件最后只执行一次。
- 防抖适用于需要等待一段时间后进行操作的情况,比如用户输入搜索框、窗口大小调整等。
- 代码:
function debounce(fn, delay = 500) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn();
timer = null;
}, delay);
};
}
const input1 = document.getElementById('input1');
input1.addEventListener(
'keyup',
debounce(function () {
console.log('input1.value:', input1.value);
})
);
3. 完整版代码
- 代码的关键区别

(1) 节流
function throttle(fn, wait) {
let previous = 0;
return function () {
let now = Date.now();
let _this = this;
let args = arguments;
if (now - previous > wait) {
fn.apply(_this, arguments);
previous = now;
}
};
}
function throttle2(fn, wait) {
let timer;
return function () {
let _this = this;
let args = arguments;
if (!timer) {
timer = setTimeout(() => {
timer = null;
fn.apply(_this, arguments);
}, wait);
}
};
}
(2) 防抖
function debounce(func, delay) {
let timeout;
return function () {
let arg = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func(arg);
}, delay);
};
}
function debounce2(fn, delay) {
let timer;
return function () {
let args = arguments;
if (timer) clearTimeout(timer);
let immediate = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
if (immediate) {
fn(args);
}
};
}
function debounce3(fn, delay, immediate) {
let timer;
return function () {
let args = arguments;
let _this = this;
if (timer) clearTimeout(timer);
if (immediate) {
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
if (callNow) {
fn.apply(_this, args);
}
} else {
timeout = setTimeout(() => {
func.apply(_this, arguments);
}, delay);
}
};
}