开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情
提到防抖和节流你会想到什么?表单的提交、模糊搜索、输入框内容校验、窗口尺寸的变化...在短时间内大量触发同一事件,不仅会使浏览的负担加重,影响性能,还会有不好的用户体验。
而防抖和节流正是解决此问题的方案之一,在前端面试中也高频出现的问题。
一般防抖会和节流进行对比记忆:
- 防抖:当用户触发某个事件的操作过于频繁,只执行最后一次对事件的操作
- 节流:当持续触发事件时,n秒内只调用一次事件处理函数,在这段时间内不会重新执行事件。
关于防抖,可参考全面面的文章:JS进阶 | 关于防抖。
节流的实现
时间戳法
核心的思路就是使用闭包,利用时间戳的差值来决定什么时候执行函数。
- 设定 prev 变量,用来记录最近一次触发函数的时间,初始为 0(这里不能像防抖一样设置成 null,因为后面需要参与计算)
- 闭包中定义一个 now 变量,存储当前的时间戳
- 如果当前时间 now 大于上一次触发的时间 prev(第一次触发事件也会是大于的关系),执行对应的方法,并将 last 设为当前最新的时间
function throttle(Fn, interval) {
var prev = 0;
return function () {
var now = new Date().getTime();
if (now - prev > interval) {
Fn.apply(this, arguments);
prev = now;
}
}
}
定时器法
- 设定一个空的定时器
- 当定时器为空时,按照一定的时间频率触发函数执行,执行后清空定时器(注:这里是和防抖的实现不同的地方)
var throttle = function(func, delay) {
var timer = null;
return function() {
if (!timer) { // timer 为 null
timer = setTimeout(function() {
func.apply(this, arguments);
timer = null; // 每触发一次事件,就清空定时器
}, delay);
}
}
}
节流的升级
按照上述代码运行后,会发现一个问题:节流函数的最后一次不会执行(无法满足 now - last > interval 的条件)。如果想要最节流函数的后一次也执行,时间戳+定时器
的组合使用可以实现。