JS防抖与节流
如我们有个需求:在窗口大小改变后,计算窗口的宽高比。
可能代码如下:
function calc() { console.log(window.innerWidth / window.innerHeight) } window.addEventListener('resize', calc)
这可以满足需求,但是当我们拉动窗口大小时发现,控制台的输出频率非常高,造成不必要的消耗。实际上我们只需要在拖动窗口结束时计算一次就可以。
所以要根据需求,做防抖或节流来优化实现。
一、防抖
1.1 什么是防抖
如果短时间内大量触发同一事件,只会执行一次函数。
1.2 实现
function debounce(fn,delay){ let timer = null //借助闭包 return function() { if(timer){ clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时 } timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时 } }
那我们上面的需求代码就可以改为
function calc() { console.log(window.innerWidth / window.innerHeight) } function debounce(fn,delay){ let timer = null return function() { if(timer){ clearTimeout(timer) } timer = setTimeout(fn,delay) } } window.addEventListener('resize', debounce(calc, 300))
那如果在改变窗口大小的过程中,就希望开始计算呢?这就要用节流
二、节流
2.1 什么是节流
如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效
2.2 实现
function throttle(fn,delay){ let valid = true return function() { if(!valid){ //休息时间 暂不接客 return false } // 工作时间,执行函数并且在间隔期内把状态位设为无效 valid = false setTimeout(() => { fn() valid = true; }, delay) } }
那我们上面的需求代码就可以改为
function calc() { console.log(window.innerWidth / window.innerHeight) } function throttle(fn,delay){ let valid = true return function() { if(!valid){ //休息时间 暂不接客 return false } // 工作时间,执行函数并且在间隔期内把状态位设为无效 valid = false setTimeout(() => { fn() valid = true; }, delay) } } window.addEventListener('resize', throttle(calc, 300))
三、更多的应用场景与总结
如:滚动条高度获取,提交按钮的连续点击造成重复提交,输入框内值变化时事件的响应等
本文只以最简单实现,用来快速学习防抖与节流的实现思路,代码不健全不建议直接使用。
参考资料: https://segmentfault.com/a/1190000018428170
2021-11-16 17:01:36
757
0
参与讨论