节流函数也是为了优化用户体验而诞生的一种技术手段,目的是为了限制事件处理函数一段时间内只能执行一次。注意了,它跟防抖函数有很大的区别:防抖函数是最后才执行一次事件处理函数,而节流函数是一段时间内就触发一次。
应用场景
- 滚动加载页面数据
- 其他需要限制事件处理函数执行频率的场景
技术原理
利用了闭包的技术原理
代码实现
function throttle(fn, delay) {
// last: 上一次触发fn函数的时间;timer: 定时器
let last, timer;
return function () {
let ctx = this; // 当前函数的执行上下文
let args = arguments; // 当前函数的参数
let now = Date.now(); // 当前函数执行时的时间
if (last && now < last + delay) {
// 如果当前函数触发时的时间间隔,小于用户指定的时间间隔,则不会执行fn事件处理函数
if (timer) return
// 设置定时器的目的是为了最后执行一次fn事件处理函数
timer = setTimeout(function () {
last = Date.now();
timer = null;
// 把args参数传递到fn函数,并且把fn函数的this指针指向ctx
// 相当于ctx.fn(args)
fn.apply(ctx, args);
}, delay)
} else {
last = now; // 更新fn函数被执行时的时间
if (timer) {
// 清除定时器
clearTimeout(timer)
timer = null
};
// 事件会立即执行,之后每间隔 delay 毫秒执行一次
fn.apply(ctx, args);
}
}
}
测试用例
function test(arg) {
console.log(arg, 'arg')
}
const cb = throttle(test, 200);
window.onscroll = function() {
console.log('window onscroll')
cb.call(this, 'throttle test')
};
通过不断的滚动页面,我们在控制台中可以观察到 test 函数一开始先执行了一次,之后每间隔 200ms 重新执行一次。