小知识,大挑战!本文正在参与“ 程序员必备小知识 ”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
前言
- 防抖节流我相信大家都不陌生,简单理解,可有效的规避很多重复性(误)操作。
- 防抖:在规定时间内,操作时长间接性小于规定时间,只执行第一次或者最后一次;如:500ms执行一次,间接时间为100ms,一共操作时长2000ms,则会执行1次。
- 节流:规定时间内执行一次,操作时长大于规定时间,则开启下一个执行;如:500ms执行一次,一共操作时长2000ms,则会执行4次。
问题所在
问题:
clearTimeout(timeout)后,timeout=???、以及定时器有什么变化?
先简单过一下 下图的代码,平淡无奇哈,但是关键在于这句 timeout && clearTimeout(timeout),试想经过clearTimeout(timeout)后,timeout=???,等于null吗?可以看到清除定时器后timeout的值并非null,而且还不变,这是不是有点匪夷所思啊?
- 接下来我们分析一下,我们开启一个定时器,并且把这个定时器记录赋给一个变量,这时候定时器在内存中,可以通过该变量对应id去查找到,经过
clearTimeout(timeout)后,只是对内存中的定时器进行清除,仅此而已,并未对变量进行修改操作; - 如果我们直接进行
timeout=null,而没有clearTimeout(timeout),那么定时器是没有清除的,只是把timeout指向变了,并没有清除掉定时器,此时定时器在内存中虽然没有变量指向它,但它仍存在内存中,待wait时间一到,就执行callback函数。
防抖函数实现
/**
* 防抖函数:多次触发事件,事件处理函数只执行一次,并且在触发操作后执行。
* 原理:利用闭包原理,就是函数需要在刚完成时需要被使用,赋值给一个变量,由这个变量去使用。
* @param {*} callback 回调函数
* @param {*} wait 延迟时间,默认500ms
* @param {*} immediate 是否立即执行,默认是
*/
export const debounce = (callback, wait = 500, immediate = true) => {
let timeout = null;
let debounced = function() {
let self = this;
timeout && clearTimeout(timeout);
if (immediate) {
let callNow = !timeout;
if (callNow) callback.apply(self, arguments);
timeout = setTimeout(() => {
timeout = null;
}, wait);
} else {
timeout = setTimeout(() => {
callback.apply(self, arguments);
}, wait);
}
};
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
节流函数实现
顺便附上节流函数
/**
* 节流函数:触发操作后,在间隔连续时间内只执行一次,过了规定间隔时间后,才进行下一次调用
* 原理:对函数进行间隔操作,在规定间隔时间内,如有重复操作,则清除掉本次操作
* @param {*} callback
* @param {*} wait 间隔时间,默认500ms
* @param {*} options = { leading: false, // 禁用第一次执行 trailing: false // 禁用停止触发的回调 }
* @returns
*/
export const throttle = (callback, wait = 500, options = {}) => {
let time, context, args;
let previous = 0;
let later = function() {
previous = options.leading === false ? 0 : new Date().getTime();
time = null;
callback.apply(context, args);
if (!time) context = args = null;
};
let throttled = function() {
let now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
let remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (time) {
clearTimeout(time);
time = null;
}
previous = now;
callback.apply(context, args);
if (!time) context = args = null;
} else if (!time && options.trailing !== false) {
time = setTimeout(later, remaining);
}
};
throttled.cancel = function() {
clearTimeout(time);
time = null;
previous = 0;
};
return throttled;
};
期待
欢迎留言和点赞收藏哦~~~