面试官:请手写一个防抖节流🤔,我:在我的博客里写了,想要啊?你去复制就好了😎防抖 基本概念 只有当事件停止触发一段时
防抖节流,前端面试中,考察频率非常高;当然在实际的开发中,许多业务场景经常也会应用到。
如果你还不知道防抖节流是啥的话,或者最近在准备面试但是忘记了,本文将带你再次学习如何手写防抖节流,让你在面试中实现一个简单的防抖节流。😘
防抖
基本概念
只有当事件停止触发一段时间后才会执行事件中的函数,确保短时间内多次触发仅在最后一次执行
场景
输入框搜索联想,频繁输入时只在用户停止输入一段时间后发送请求
防抖丐版实现
分析
前面触发的点击事件我们没有去执行,但是到最后一次触发事件后的等待期结束后执行

代码
<body>
<button id="btn">提交</button>
<script>
const btn = document.querySelector('button')
function sendMsg(msg) {
const currentDate = new Date();
console.log('sendMsg函数的this指向是',this,'\n',
'点击事件传递进来的参数是',msg,'\n',currentDate.toLocaleString())
}
btn.addEventListener('click', debounce(sendMsg, 1000))//防抖函数
// btn.addEventListener('click', sendMsg)//没有防抖的话
function debounce(fn, delay) {
let timer
return function(){
let args = arguments
if(timer) clearTimeout(timer)
timer = setTimeout(()=>{
fn.call(this,...args )
},delay)
}
}
</script>
</body>
代码讲解
我们使用debounce
函数来包裹要执行的函数,传入设置的时间间隔;
debounce
函数中使用到了闭包来保证多次调用的话timer
变量的一致性,
执行一次debounce
函数就会对计时器timer
变量判断,如果有计时器就重新设定,如果在设定的间隔中触发,那么定时器就会不断刷新,实现最后一次等待之后再触发,来实现防抖效果
这里的call
方法和arguments
对象
如果需要执行的函数fn
如果当中有通过this
指向dom对象的代码的话,因为fn
函数被节流函数debounce
包裹,所以需要使用call
来设定正确fn
的this
指向
又因为函数fn
可能也需要依赖点击事件传入的参数,所以通过使用arguments对象来获取到传入debounce
函数返回的匿名函数的参数,来确保代码正确运行
效果
没有防抖,触发一次点击事件就立马执行,要执行的函数逻辑
开启防抖,只在最后一次事件触发之后再执行函数
节流
基本概念
节流就是在过了特定时间间隔被触发事件中的函数执行一次,周期性地执行被触发事件中的函数,而不限制最后一个事件
应用场景
滚动事件监听,实时更新但不密集执行,如滚动加载
还有一个非常常见的场景,就是在打游戏的时候想多打出点伤害,手速通常会很快,但是 游戏中按键连击,只会确保每段时间只触发一次伤害计算
节流丐版实现
分析
节流概括来说就是,按照固定的时间间隔执行,无视触发频率
代码
<body>
<button>按钮</button>
<script>
let btn = document.querySelector('button')
function sendMsg(e) {
const currentDate = new Date()
console.log('sendMsg的this指向是',this,'\n','点击事件传递进来的参数时',e,'\n',currentDate.toLocaleString())
}
btn.addEventListener('click',throttle(sendMsg,1000))//节流函数
//没有节流
//btn.addEventListener('click',sendMsg)
function throttle(fn,wait) {
let preTime = Date.now()
return function () {
let nowTime = Date.now()
if (nowTime - preTime >= wait) {
fn.apply(this,arguments)
preTime = nowTime
}
}
}
</script>
</body>
代码讲解
了解到防抖之后,节流也就非常好理解了
Date.now()
将会得到一个表示自 1970 年 1 月 1 日 00:00:00 UTC 以来所经过的毫秒数的整数值。
这个方法是 Date
对象的一个静态成员函数,意味着你无需创建 Date
对象实例就能调用它
通过闭包设定一个初始时间保证多次调用函数都是这个变量,如果函数的执行时间-初始时间大于或等于设定的时间间隔,则执行函数,并刷新初始时间,否则啥也不干;就可以实现等待设定的时间之后才能触发的节流效果。
这里的arguments
对象没有解构是因为apply
方法接受数组为参数。
实现效果
使用节流函数,多次点击因为小于设定好的时间间隔所以并不会执行,只有当等待时间等于或者大于设定好的间隔才会执行
还在学习中,水平有限,本文可能存在纰漏或错误,如有问题欢迎指正,感谢你阅读这篇文章,如果你觉得写得还行的话,不要忘记点赞、评论、收藏哦!祝生活愉快!😘
本人目前在准备春招,也希望和一起准备春招的佬们互相交流一下,一起冲刺大厂,欢迎私信评论或加v:guanyiiu1314
转载自:https://juejin.cn/post/7343132138655711268