前言
经常写业务代码的你现在还能手写出节流与防抖函数,作为面试高频问答题,可谓是在找工作中‘居家必备’呀;如果你不会不妨再来学习巩固,下面会通过几个案例带大家了解
防抖函数
定义:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
通过定义我们大概在脑海中想到些思路,比如n秒后再执行回调,那么这很明显我们需要定义个回调函数,js中能直接使用的回调函数就那么几个又是n秒后,显然对吧,定时器;那定时器怎么定义的呀,再来回顾下
MDN定义: WindowOrWorkerGlobalScope 混合的 setTimeout()方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。
语法
var timeoutID = scope.setTimeout(function[, delay, arg1, arg2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);
参数
function
function 是你想要在到期时间(delay毫秒)之后执行的函数
delay 可选
延迟的毫秒数 (一秒等于1000毫秒),函数的调用会在该延迟之后发生。如果省略该参数,delay取默认值0,意味着“马上”执行,或者尽快执行。不管是哪种情况,实际的延迟时间可能会比期待的(delay毫秒数) 值长,原因请查看实际延时比设定值更久的原因:最小延迟时间。
好了了解定时器了,我们来看下那到底怎么实现呢
//通过定义来的话,我们代码是不是应该这么写
伪代码
function fn(){
console.log('哈哈delay秒后我被执行了')
}
setTimeout(() => {
fn()
}, delay)
//在演变下,封装个函数是不是就实现呢,那这好像不太对
function debounce(fn, delay = 300) {
setTimeout(() => {
fn()
}, delay)
}
//如果在这n秒内又被触发,则重新计时。我们在加上这个
function debounce(fn, delay = 300) {
//如果又被触发,则重新计时
if (timer) {
clearTimeout(timer)
}
//执行的时间
timer = setTimeout(() => {
fn()
}, delay)
}
//完整代码
function debounce(fn, delay = 300) {
let timer = null
//这里使用闭包,至于为什么使用闭包,不妨思考下
return function (...args) {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
// 每次事件被触发时,都去清除之前的旧定时器
if (timer) {
clearTimeout(timer)
}
// 设立新定时器
timer = setTimeout(() => {
//再思考这里为什么改变this指向
fn.apply(context, args)
}, delay)
}
}
节流函数
定义:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
节流函数相比防抖就好理解的多,比如规定在一个单位时间内,只能触发一次函数;
那我规定300ms触发一次
function fn(){
console.log('哈哈delay秒后我被执行了')
}
function throttle(fn, delay = 300) {
let now = +new Date()
let last = 0
if (now - last >= delay) {
last = now
fn()
}
}
}
//
function throttle(fn, delay = 300) {
console.log('delay', delay)
// last为上一次触发回调的时间
let last = 0
//这里使用闭包,至于为什么使用闭包,不妨思考下
return function (...args) {
// 保留调用时的this上下文
let context = this
// 记录本次触发回调的时间
let now = +new Date()
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= delay) {
last = now
//再思考这里为什么改变this指向
fn.apply(context, args)
}
}
}
理解及应用场景
理解:其实网上有个说法非常容易理解节流防抖,都玩过pvp类的游戏吧
防抖:就像法师放技能,不能重复放,放完有冷却时间,被打断了只能重新放
节流:就像射手射出的子弹,规定的时间内他就只能有那些攻速
应用场景:
防抖的应用场景主要:按钮的点击(短信按钮的发送防止手贱客户拼命点击);模糊搜索输入框内的关键字(如百度);窗口缩放长宽的计算;文本编辑器实时保存(博客发布文章编辑器);
节流的应用场景主要:鼠标不断点击;滚动条的下拉监听(scroll时间)
结束语
这里我留下了两个问题,防抖和节流里面为什么使用闭包以及this的指向问题,欢迎在评论区给出你的答案,如果大家能给出不错的答案说明你已经熟练掌握了以后面试在被问道赶紧吊打面试官;最后,文章能给你带来帮助欢迎一键三连多多支持下我~,谢谢