JS实现防抖和节流
前⾔:
防抖和节流在js中有很多应⽤的场景,⽐如监听滚动条事件,输⼊字符搜索次数的优化等等。不能只知其然⽽不知其所以然,所以有必要了解下实现的原理。
区别:
防抖是在⼀段时间内不能执⾏某种操作。⽐如在搜索框这个场景,只有在500ms后没有输⼊新的字符,才会去调⽤接⼝进⾏搜索。 节流则是有规律的执⾏某种操作。⽐如监听滚动条事件这个场景,在⼀直滚动时,每隔300ms会执⾏⼀次滚动条事件的回调。
防抖:
/**
* 函数防抖
* @param func ⽬标函数
* @param delay 延迟时间
* @param immediate 是否⽴即执⾏,是指在触发后是否先执⾏⼀遍⽬标函数
*/
function debounce (func, delay, immediate) {
let timer = null; // 通过闭包来保存timer的值
let _debounce = function () {
const context = this;
const args = arguments;
if (timer) {
clearTimeout(timer);
}
if (immediate) {
let callNow = !timer; // 如果timer为null说明是第⼀次执⾏
timer = setTimeout(() => {
timer = null;
}, delay);
if (callNow) {
func.apply(context, args);
}
} else {
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
}
}
_debounce.cancel = function () {
clearTimeout(timer);
timer = null;
}
return _debounce;
}
节流:
/**
* 函数节流
* @param func ⽬标函数
* @param delay 延迟时间
* @param options options.leading:是否在刚触发后⽴即执⾏⽬标函数
* ailing:是否在停⽌触发后还执⾏⼀次⽬标函数
*/
function throttle (func, delay, options) {
let timer;
let previous = 0; // 上⼀次执⾏的时间点
options = options || {};
const _throttle = function () {
const context = this;
const args = arguments;
const now = +new Date();
// 如果leading为false,则设置上⼀次执⾏的时间点为当前,⾃然也就不会⽴马执⾏⽬标函数了
if (!previous && options.leading === false) {
previous = now;
}
// 计算距离上次执⾏的时间点还剩多少时间
const remaining = delay - (now - previous);
// 如果剩余时间⼩于等于0,说明从上次执⾏到当前已经超过了设定的delay间隔
// 如果剩余时间⼤于设定的delay,说明当前系统时间被修改过
if (remaining <= 0 || remaining > delay) {
if (timer) {
clearTimeout(timer);
timer = null;
}
func.apply(context, args);
previous = now;
} else if (!timer && ailing === true) {
timer = setTimeout(() => {
// 如果leading为false代表下次触发后不需要⽴马执⾏⽬标函数,所以设置为0,在17⾏才会顺利进⼊判断
previous = options.leading === false ? 0 : +new Date();
func.apply(context, args);
timer = null;
js arguments}, remaining); // 此处设定为计算距离上次执⾏的时间点剩余的时间,使⽤setTimeout保证了即使后续不触发也能再执⾏⼀次⽬标函数 }
}
_throttle.cancel = function () {
clearTimeout(timer);
timer = null;
previous = 0;
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论