什么是防抖?什么是节流?
防抖:用户触发高频事件(比如说点击事件)后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间,n秒后再执行。总之,就是等待用户触发完事件n秒内不再触发事件,再执行函数。
节流:用户触发高频事件(比如说点击事件)后n秒内函数只会执行一次。也就是说,不论用户在n秒内触发多少次事件,最终函数都会在n秒后执行一次。
防抖和节流的应用场景
防抖:
- 登录、发短信等按钮,避免发送多次请求
- 文本编辑器的自动保存
- input输入框,每隔特定时间发送请求(输入搜索)或者展开下拉列表(节流也可以)
节流:
- scroll滚动事件,每隔特定时间执行回调函数
- 浏览器窗口大小resize,避免次数过于频繁(防抖也可以)
手动实现防抖和节流
防抖
//debounce函数接收两个参数,第一个是要执行的函数,第二个是指定的时间间隔,也就是上述的n
function debounce(fn, delay) {
//定时器
let timer = null;
return function(...args) {
//保存上下文的this
let ctx = this;
//如果定时器已经存在,则清除定时器
if (timer) {
clearTimeout(timer);
}
//设置定时器
timer = setTimeout(function() {
//使用apply执行函数fn
fn.apply(ctx, args);
},delay);
}
}
节流
function throttle(fn, delay) {
//由于节流是指定时间后必运行一次,所以我们需要一个标记来判断是否到了可以运行的时候,第一次触发必然是可以运行的,所以初始化为true
let canRun = true;
return function(...args) {
let ctx = this;
if (!canRun) return;
//第一次触发事件后,立即设置为false
canRun = false;
//设置定时器
setTimeout(function() {
fn.apply(ctx, args);
//当到了指定时间函数运行一次后,是否可以运行标志又变为true,表示可以进行下一次循环
canRun = true;
},delay)
}
}
测试:大家可以把如下代码代入,然后改变浏览器窗口的大小,体验下防抖和节流的效果。
function resizeWindow(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', debounce(resizeWindow, 1000))
//window.addEventListener('resize', throttle(resizeWindow, 1000))