防抖和节流的一个明显区别就是:一次执行后,防抖可再次执行时间是动态的,节流可再次执行时间是固定的。
防抖
每次事件触发后,延后n秒再执行函数。如果这n秒期间,又发生了新的触发,原有任务取消,以最新触发为准,n秒后执行。
基础版
function debounce(fn, wait = 1500) {
let timer;
return function () {
let args = arguments
let context = this;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args)
}, wait);
}
}
增强版(增加了 立即执行、可返回值、可取消三个功能)
第一次触发时立即执行,最后一次触发 n 秒之后可重新执行
function debounce(func, wait) {
let timer;
function debounced() {
let context = this;
let args = arguments;
clearTimeout(timer);
let callNow = !timer; // setTimeout的结果是正整数
timer = setTimeout(function(){
timer = null;
}, wait)
if (callNow) {
return func.apply(context, args)
}
}
debounced.cancel = function () {
clearTimeout(timer);
timer = null
}
return debounced
}
节流
如果持续触发事件,每隔一段时间,只执行处理函数一次
基础版
// 时间戳方式
function throttle(fn, wait) {
let previous = 0;
return function () {
let context = this;
let args = arguments;
let now = new Date().getTime();
if (now - previous > wait) {
return fn.apply(context, args)
}
}
}
// 定时器方式
function throttle(fn, wait) {
let timer;
return function () {
let context = this;
let args = arguments;
if (!timer) {
fn.apply(context, args)
timer = setTimeout( () => {
timer = null;
}, wait)
}
}
}
增强版
多次触发时,能立即执行一次,n 秒限制之后再执行一次。(相当于提供一次预约机会)、能返回值、能取消
function throttle(fn, wait = 1500) {
let previous = 0;
let timer;
function throttled() {
let context = this;
let args = arguments;
let now = new Date().getTime();
// 剩余隔离时间
let quarantine = previous + wait - now;
if (quarantine <= 0) {
previous = now;
return fn.apply(context, args)
} else if (!timer) {
timer = setTimeout( () => {
previous = now;
timer = null;
return fn.apply(context, args)
}, quarantine)
}
}
throttled.cancel = function() {
clearTimeout(timer);
previous = 0;
timer = null;
}
return throttled
}
网友评论