概述
在平时的开发中,经常会听到两个差不多很相近的词。节流(throttle)和防抖(debounce)。这是两个类似又有些不同的优化方案。
节流:在指定时间之内,让函数只触发一次。
防抖:对于一定时间段的连续的函数调用,只让其执行一次。
两个方法在underscore.js中都已经实现了。本文将会重点说明两个函数的应用场景和背后的原理。
应用场景
节流
throttle在英语里的意思是节流阀,顾名思义,设置一个阀值(制定一个时间),在这个阀值或者时间之内,函数只会执行一次。
举个例子,我们执行页面滚动的时候,比如在react里面,可能每次滚动都会触发一次render,这样严重影响性能,甚至会造成浏览器卡死。如果我们设置一个300ms的时间阀,那么在这段时间内,滚动时候只会触发一次render.
同样的,当我们拖拽某个元素的时候,会每次判断mousemove时跟位置相关的信息,每次都会执行相关的计算和判断,这种情况就和滚动时候一样,如果设置一个时间阀,那么就可以避免由于大量执行事件计算而造成的性能下降。
防抖
我自己的理解,防抖的意思可以认为是,阻止连续的抖动(所谓的事件触发),也就是说,我们用防抖来让那些连续触发的事件只触发一次。
比如,当我们对一个文本框进行输入的时候,在react中,每次都会触发onChange事件,我们可能在每次事件里发送ajax请求,判断输入的用户名是否曾经注册过,这种情况下我们使用防抖,可以保证只会在最后一次onChange事件才会触发ajax请求。
实现原理
节流
节流实现起来很好理解,设置一个bool值,在时间阀之内,根据这个bool来判断是否执行函数。
function throttle(fn,times = 300){
let bool = true
return function(){
if(!bool){
return false
}
bool = false
setTimeout(()=>{
bool = true
fn.apply(this,arguments)
},times)
}
}
防抖
防抖实现起来的思路是,用闭包保存执行的函数,多次执行的时候把上一个执行的函数清除掉,然后再次创建一个新的函数。这样在间隔时间内还有事件触发的话,不会执行之前的函数,这么一来,函数真正的执行就是最后一次事件触发。
function debounce(fn,times){
let timeout = null
return function(){
clearTimeout(timeout)
timeout = setTimeout(()=>{
fn.apply(this,arguments)
},times)
}
}
总结
以上只是很简单的写了一下节流和防抖的原理,在underscore.js里,实现起来更加复杂,但是背后的原理核心就是上边代码写的。两者都是在密集调用的过程中灵活使用setTimeout函数来对频繁触发的事件进行控制和优化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。