持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
这是源码共读的第2期,链接:juejin.cn/post/708744…
什么是防抖
在触发事件n秒后才执行,也就是说,尽管触发事件,在事件触发的n秒内又触发了这个事件,就重新计算,以这次触发事件的时间为准,n秒后再执行。也就是,等你触发完事件n秒内不再触发事件,才执行。
防抖的作用
日常开发中,防抖主要用在页面事件点击上,比如请求事件,或跳转页面,如果不做防抖的话,用户频繁触发的话,就会在短时间多次执行相关的事件,导致异常的卡顿,或无意义的多次请求,多次跳转。
如何实现防抖
根据上面的作用,我们可以考虑下如何实现防抖:
- 在触发事件之后n秒执行,则需要依赖
setTimeout来实现。 - 涉及到事件等异步方式,则this指向也是需要考虑的。
- 同时还需要考虑事件event对象的传递
- 最后就是要考虑如何取消防抖
来看下代码实现:
function debounce(fn, delay) {
var _debounce = function (args) {
let that = this;
let _args = args;
clearTimeout(fn.id);
fn.id = setTimeout(function () {
fn.apply(that, _args);
}, delay)
}
_debounce.cancel = function(){
clearTimeout(fn.id);
fn.id = null;
}
return _debounce;
}
underscore中防抖的实现
import restArguments from './restArguments.js';
import now from './now.js';
// When a sequence of calls of the returned function ends, the argument
// function is triggered. The end of a sequence is defined by the `wait`
// parameter. If `immediate` is passed, the argument function will be
// triggered at the beginning of the sequence instead of at the end.
export default function debounce(func, wait, immediate) {
var timeout, previous, args, result, context;
var later = function() {
var passed = now() - previous;
if (wait > passed) {
timeout = setTimeout(later, wait - passed);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
// This check is needed because `func` can recursively invoke `debounced`.
if (!timeout) args = context = null;
}
};
var debounced = restArguments(function(_args) {
context = this;
args = _args;
previous = now();
if (!timeout) {
timeout = setTimeout(later, wait);
if (immediate) result = func.apply(context, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = args = context = null;
};
return debounced;
}
underscore中的实现,作为开源项目,比我们自己实现的要严谨很多,健壮很多,这就是我们学习开源库的目的,学习开源项目在写一些工具函数时,都会考虑哪些?比如:函数的抽象、参数的校验、边界条件的判断等等,都是需要我们特别要注意的,这些在日常开发中是比较容易忽略的,大部分都是以满足现有需求为主。
需要注意的是,underscore的实现中多了立即执行的能力。
- immediate该参数表示,不需要等待,直接执行,以满足一些特殊场景的使用。
总结
防抖、节流是我们必须要掌握的,任何一个前端业务项目都会涉及到这块,只要有点击事件,或滚动事件都会用到。大部分时候我们都是引用工具库的,或者自己内部项目的工具库,因此了解其原理及应用场景是一个前端开发必备的知识点。