这是前端性能优化的基础知识,使用频率也非常高,建议掌握。
防抖
防抖,debounce /di'bauns/,它其实是来源于电学术语“去弹跳”。当你按下一个按钮时,由于信号传递十分迅速,但是部件在连接和断开状态之间不稳定,所以会多次触发信号。为了缓解这种情况,我们会在接收到按钮信号之后的一段时间内忽略来自它的信号。
在 JavaScript 中也是同理,如果遇到需要忽略一段时间内的同一个动作,只执行最后一次,那么就可以运用它来避免性能浪费。例如,在用户完成输入之后才显示搜索建议。
为了达到这一目的,可以使用定时器来延迟执行函数,下次触发时如果上一个定时器还没有结束,就取消它并创建一个新的定时器。完整代码是这样:
function debounce(fn, delay) {
let timer
return function () {
let that = this,
args = arguments
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(function () {
fn.apply(that, args)
}, delay)
}
}
这是防抖函数的一种实现方式,其中涉及闭包和修改 this
指向的知识。
节流
再看节流,throttle /ˈθrɑːtl/。顾名思义就像在河道上建了一个水坝,目的是控制水的流速,不能彻底截断水流。
体现在 JavaScript 里就是函数执行一次后被锁定不允许触发,等一段时间再恢复触发。这有点像游戏里的技能 CD,你释放完技能后它就灰掉了,必须等待一段时间才可以继续释放。
截流函数的实现代码如下:
function throttle(fn, delay) {
let wait = false
return function () {
let that = this,
args = arguments
if (!wait) {
wait = true
setTimeout(function () {
fn.apply(that, args)
wait = false
}, delay)
}
}
}
它同样是使用定时器,与防抖不同的是,设置了一个标志在一段时间内锁定它。
对比
节流和防抖有点像,它们的不同之处在于,节流改变了频繁触发的函数的执行频率。
你可以通过 这个页面 去实际体验它们的不同。
总结
一般遇到 高频率事件 就需要注意了,是否会对浏览器性能照成影响,是否需要使用节流和防抖动?
根据它们各自的功能,针对业务场景可以自由的选择使用。使用节流的地方也可以使用防抖,具体看你希望达到的效果。
它们的核心内容不复杂,但是在日常开发中,我不会自己去单独实现它们,而是会使用开源库1提供的方法,这样更加安全和方便。