开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情
前言
防抖节流是常见的面试题,在日常开发过程中我们也会用来优化,理解实现方式并且能够手写出来是我们必须要掌握的,今天我们就来看一下如何手写防抖节流。
防抖
定义
防抖:在事件触发n秒后再执行代码,期间点击一次就会重新计时。防抖常用于能够连续触发事件但只想要执行一次的场景,比如:输入框输入搜索,输入完等待一段时间再进行执行。
实现
防抖的特点是在规定事件触发会重新计时,要想实现这一个功能:
- 实现n秒后再运行,通过设置延时器——setTimeout(),delay就是规定的时间。
- 闭包写法,为了全局变量的影响,我们将写成闭包形式,return一个函数,函数就是延时器,延时器里面就是我们想要执行的函数fun
- this指向问题,在setTimeout中this指向当前的window,当我们执行fn传参时,就需要改变this指向,不然获取不到执行对象。 经过上面三个步骤的考虑我们就能得到防抖函数:
function debounce(fun, delay) {
//fun 执行函数 delay 延迟时间
let timer;
//写成闭包形式 return一个函数
return function () {
const _this = this;
const args = arguments;
if (timer) {
//有定时器清除
clearTimeout(timer);
}
timer = setTimeout(function () {
//用apply改成this指向,使其指向执行的实例
fun.apply(_this, args);
}, delay);
};
}
节流
定义
节流:在n秒内多次触发事件,就只会执行一次。比如:用户疯狂点击搜索按钮,如果不做节流处理,会重复向后端发送请求,这种情况可能会导致报错。
实现
节流的特点是n秒内只触发一次,跟着这个思路:
- n秒后触发一次,也是一个延迟执行的函数,所以我们还可以使用setTimeout()实现。
- 只触发一次,我们可以进行判断,比如setTimeout存在就返回,不去执行;还有一种思路就是时间戳,获取第一次点击的时间戳保存起来,每次点击都获取当前时间戳,两者相减与规定时间做对比,小于规定时间就返回,不去执行。
- 闭包形式,节流我们也使用闭包形式的写法。
//延时器写法
function throttle1(fun, delay) {
let timer;
//写成闭包形式 return一个函数
return function () {
const _this = this;
const args = arguments;
//首次将timer进行赋值,再次点击后判断为false不会执行
if (!timer) {
timer = setTimeout(function () {
fun.apply(_this, args);
timer = null; //执行完赋值为null
}, delay);
}
};
}
//时间戳写法
function throttle2(fun, delay) {
//首次时间
let firstTime = new Date().getTime();
return function () {
//获取当前时间进行对比
const _this = this;
const args = arguments;
const nowTime = new Date().getTime();
if (nowTime - firstTime >= delay) {
fun.apply(_this, args);
firstTime = new Date().getTime(); //执行完重新赋值
}
};
}
总结
防抖就像打游戏时候回城,回城期间再点会重新计算回城时间,适用于连续触发事件,比如监听滚动条事件;节流就像按技能,按多次还是只会释放一次,当用户疯狂点击请求时,可以防止一直发送请求。