前言
前端的交互中,有些操作需要持续触发,而且频率非常高。比如:resize, scroll, mousemove, input等事件。而为了性能和效率,我们不需要让事件触发太多次。这就诞生了函数的防抖和节流。
防抖(debounce)
防抖简单说就是在设定的时间内,虽然操作上持续触发,通过定时器约束,我们也只执行函数触发的最后一次。
防抖函数可以分为延迟执行版和立即执行版
延迟执行版
/*
fn: 需要防抖的函数
wait: 延迟毫秒数
return: 函数
*/
// 延迟执行
function debounce(fn, wait) {
var timer; // 全局的定时器 id
return function () {
var that = this; // 将函数被调用时的 this 保存
var args = arguments; // 保存函数的参数
if (timer) {
clearTimeout(timer); // 清除 wait 时间内频繁调用函数产生的定时器
}
timer = setTimeout(() => {
fn.apply(that, args); // 将传递进来的 fn 使用 apply 调用,将 this 指向改为保存的 that,同时进行传参
}, wait);
};
}
立即执行版
// 立即执行
function debounce(fn, wait) {
var timer;
return function () {
var that = this;
var args = arguments;
if (timer) {
clearTimeout(timer);
}
if (!timer) fn.apply(that, args); // 首次进入, timer 为空,执行 fn 函数
timer = setTimeout(() => {
timer = null; // wait 毫秒后设置 timer 为空
}, wait);
};
}
防抖应用场景
- reseize 事件
- 按钮 click 控制
节流(throttle)
节流就是按照给定的时间有规律的执行函数,可以通过时间戳和定时器实现。
节流函数可以分为定时器版和时间戳版
定时器版
// 定时器版
function throttle(fn, wait) {
let timer;
return function () {
const that = this;
const args = arguments;
if (!timer) {
timer = setTimeout(() => {
fn.apply(that, args);
timer = null;
}, wait);
}
};
}
时间戳版
// 时间戳版
function throttle(fn, wait) {
let previous = 0;
return function () {
const that = this;
const args = arguments;
let now = Date.now();
if (now - previous > wait) {
fn.apply(that, args);
previous = now;
}
};
}
节流应用场景
- 元素拖动
- 搜索联想
- 移动端上滑加载时判断距离底部的位置