一、使用背景
在浏览器中可视窗口大小的改变,窗口的滚动以及输入框的搜索和校验等操作,都会导致操作函数在极短的时间内被触发多次,但是在大部分情况中我们只需要触发一次即可。因而在这种情况下,会加重浏览器的负担,降低用户的体验。因此,我们采用debounce(防抖)和throttle(节流)的方式来减少操作函数触发的频率而又不影响效果。
二、函数防抖
当持续触发事件时,debounce 会合并事件且不会去触发事件,当一定时间内没有再触发这个事件时,才真正去触发事件。
代码演示:
1.非立即执行版:
触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
function debounce(func, delay) {
let timer; // 给定时器占个位
return function () {
// 关闭上一次开启的定时器
clearTimeout(timer);
// 重新设置一个定时器
timer = setTimeout(() => {
func.apply(this, arguments);
}, delay);
};
}
2.立即执行版:
触发事件后函数会立即执行,然后 n 秒内不再触发事件,然后触发才能继续执行函数的效果。
function debounce(func, delay) {
let timer; // 给定时器占个位
return function () {
// 关闭上一次开启的定时器
clearTimeout(timer);
// 第一次触发时定时器的值为null
let isFirst = !timer;// 定时器被关闭后取反也是true
// 重新设置一个定时器
timer = setTimeout(() => {
// 一段时间后将定时器设为null,不影响下一次
timer = null;
}, delay);
// 若是第一次触发就执行函数
if(isFirst) func.apply(this,arguments)
};
}
三、函数节流
当持续触发事件时,保证隔间时间触发一次事件。throttle 会合并一定时间内的事件,限制一个函数在一定时间内内只能执行一次
代码演示:
function throttle(func, delay) {
let timer;
return function () {
// 如果timer存在,就继续执行已经存在的timer
if (timer) return;
timer = setTimeout(() => {
func.apply(this, arguments);
// 执行完毕后把timer赋值为null,不影响下次
timer = null;
}, delay);
};
}