防抖(debounce): 当持续触发事件时,一段时间没有再触发事件,事件触发函数才会执行一遍;如果设定时间还没到来之前,事件又被触发,就重新开始计时。
节流(throttle): 当持续触发事件时,保证在一定的时间内只触发一次事件处理函数。
常用的防抖节流库:underscore、lodash
防抖:
/**
* 防抖函数,手动绑定this
* @param fn 需要执行的函数
* @param wait 执行需要等待的时间
* @param immdiate 是否立即执行函数
*/
function debounce(fn, wait, immediate=false) {
let timer = null;
let ctx = null;
const debounced = function(...rest) {
ctx = this;
if(timer) clearTimeout(timer);
if(immediate && !timer) {
fn.apply(ctx,rest);
timer = setTimeout(() => {
timer = null;
}, wait)
} else {
timer = setTimeout(() => { // 这里也可以直接使用this
fn.apply(ctx, rest)
}, wait)
}
};
debounced.cancel = function() {
if(timer) {
clearTimeout(timer);
timer = null;
}
}
return debounced
}
节流:
1)采用时间戳,第一次会执行,最后一次不会执行
/**
* 采用时间戳,
* @param fn 实际需要执行的函数
* @param wait 函数执行间隔时间
* @options 一些额外选项,此方法用不上
*/
function throttle(fn, wait, options) {
let old = 0;
return function(...rest) {
const now = Date.now();
if(now - old > wait) {
fn.apply(this, rest);
old = now;
}
}
}
2) 采用定时器,第一不会执行,最后一次会执行
/**
* 节流函数,采用定时器
* @param fn 实际需要执行的函数
* @param await 函数执行间隔的时间
* @param options 一些额外的参数,此处不会用到
*/
function throttle(fn, await, options) {
let timer = null;
return function(...rest) {
if(timer === null) {
timer = setTimeout(() => {
fn.apply(this, rest);
timer = null
}, wait)
}
}
}
3)同时采用时间戳和定时器,根据options中的选项,才确定第一和最后一次会不会执行
options.leading === true 则第一次会执行
options.trailing === true 则最后一次会执行
/**
* 节流函数,综合使用时间戳和定时器
* @param fn 实际要执行的函数
* @param wait 函数执行需要间隔的时间
* @param options 可配置参数,leading为true表示第一次执行,trailing为true表示最后一次执行
* leading和trailing 不能同时为false
**/
function throttle(fn, wait, options) {
let old = 0;
let timer = null;
const leading = options.leading || false;
const trailing = options.trailing || false;
return function(...rest) {
const now = Date.now();
if(leading === false) {
old = now
}
if(now - old > wait) {
fn.apply(this, rest);
old = now;
if(timer) {clearTimeout(timer)}
timer = null;
}else if(trailing === true && timer === null) {
timer = setTimeout(() => {
fn.apply(this, rest);
timer = null;
old = now;
}, wait)
}
}
}
// 以上代码参考underscore