函数防抖和节流都是控制事件触发频率的方法,应用场景也有很多,如:
1.输入框持续输入,将输入内容传给服务端进行校验;
2.多次触发点击事件;
3.onSroll滚动条滚动事件;
4.onmousemove鼠标移动事件;
案例
为了说明问题,假设一个场景:鼠标滑过一个div,触发onmousemove事件,它内部的文字会显示当前鼠标的坐标。它的效果是这样的
>>函数防抖(debounce)
这里的“抖”就是函数被触发了,而一般的抖动都是多次并且持续性的。假设一个函数持续多次执行,我们希望它冷静下来几秒之后再执行。也就是当事件持续触发的时候不执行,等最后一次触发结束的一段时间之后再执行。
>>函数节流(throttle)
节流就是让函数有节制的去执行,而不是每次触发都去执行。也就是在规定的时间内,只执行一次。
>>代码实现
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
* 立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果(第一次触发事件之后会执行,下一次触发之后如果距离上一次触发的时间小于n秒那就不会再执行,大于的话才会执行)
* 非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间(首次触发不执行,事件触发后的停顿时间超过n秒会自动执行)
*/
function debounce(func, wait, immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
}
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
*/
function throttle(func, wait, type) {
let previous,timeout;
if (type === 1) {
previous = 0;
} else if (type === 2) {
// let \\timeout;
}
return function () {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
//调用
document.getElementById("box-debounce").addEventListener('mousemove',debounce(function(e){
document.getElementById("box-debounce").innerHTML = e.clientX +","+e.clientY;
},1000,true))
//调用
document.getElementById("box-throttle").addEventListener('mousemove',throttle(function(e){
document.getElementById("box-throttle").innerHTML = e.clientX +","+e.clientY;
},1000,2))