本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
1.防抖是什么
在事件触发后n秒后执行回调函数,如果n秒内再次触发,则重新计算时间
2.防抖的使用场景
鼠标事件:click,mousemove,mouseover
键盘事件: keydown,keyup
window事件: resize,scroll
以上事件频繁触发就可能引起多次请求或页面卡顿,为了规避这种情况,就需要控制回调函数的执行次数。常见的有防抖和节流,本次介绍underscore的防抖函数。
3.简易版防抖
function debounce(callback,wait=0){
let timer=null;
return function(){
let args = arguments;
let context = this;
clearTimeout(timer);
timer= setTimeout(() => {
callback.apply(context,args)
}, wait);
}
}
4.underscore的防抖
-
git仓库: - github.com/jashkenas/u…
-
代码
/**
*
* @param {*} func 回调函数
* @param {*} wait 等待时间
* @param {*} immediate 是否立即执行回调函数
* @returns
*/
function debounce(func, wait, immediate) {
var timeout, previous, args, result, context;
var later = function() {
//计算是否超时
var passed = now() - previous;
if (wait > passed) {
//距离上一次调用已经过了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为null。如果immediate=true,立即执行回调函数
timeout = setTimeout(later, wait);
if (immediate) result = func.apply(context, args);
}
return result;
});
//取消防抖的定时器
debounced.cancel = function() {
clearTimeout(timeout);
timeout = args = context = null;
};
return debounced;
}
function restArguments(func, startIndex) {
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
var length = Math.max(arguments.length - startIndex, 0),
rest = Array(length),
index = 0;
for (; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
switch (startIndex) {
case 0: return func.call(this, rest);
case 1: return func.call(this, arguments[0], rest);
case 2: return func.call(this, arguments[0], arguments[1], rest);
}
var args = Array(startIndex + 1);
for (index = 0; index < startIndex; index++) {
args[index] = arguments[index];
}
args[startIndex] = rest;
return func.apply(this, args);
};
}
5.总结
学到了underscore里的防抖原理和设计思想。 防抖在项目中经常用到,一般使用插件的debounce方法或者自己实现一个简易版的。下次对比下lodash的防抖方法。