debounce & throttle | 防抖 & 节流
防抖 -> 定时器外重置&清除定时器 节流 -> 定时器内重置&清除定时器
debounce | 防抖
防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。
/**
** 防抖函数,返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
** @param {function} func 回调函数
** @param {number} wait 需要等待的时间,单位毫秒
** @param {boolean} immediate 设置为true时,是否立即调用函数
** @return {function} 返回客户调用函数
**/
function debounce(func, wait = 50, immediate = true) {
let timer, context, args;
// 延迟执行函数
const later = () => setTimeout(() => {
// 延迟函数执行完毕,清空缓存的定时器序号
timer = null;
// 延迟执行的情况下,函数会在延迟函数中执行
// 使用到之前缓存的参数和上下文
if (!immediate) {
func.apply(context, args);
context = args = null;
}
}, wait);
// 这里返回的函数是每次实际调用的函数
return function(...params) {
// 如果没有创建延迟执行函数(later),就创建一个
if (!timer) {
timer = later();
// 如果是立即执行,调用函数
// 否则缓存参数和调用上下文
if (immediate) {
func.apply(this, params);
} else {
context = this;
args = params;
}
// 如果已有延迟执行函数(later),调用的时候清除原来的并重新设定一个
// 这样做延迟函数会重新计时
} else {
clearTimeout(timer);
timer = later();
}
};
}
throttle | 节流
节流:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
/**
* 节流函数 (第一次和最后一次都会执行)
* @param {function} func 回调函数
* @param {number} delay 延迟时间
* @returns {function} 返回客户调用函数
*
* */
function throttle(func, delay) {
let start = 0, timer=null;
return function (...args) {
let now = Date.now();
if (now - start < delay) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => { // 保证在当前时间区间结束后,再执行一次func
start = now;
func.apply(this, args);
}, delay);
} else {
start = now;
func.apply(this, args);
}
}
}