“节流”,字典上这么解释:javascript
[throttle]∶节制流入或流出,尤指用节流阀调节。java
那节流函数 (throttle) 就是 “节制流入或流出的函数”,愈来愈绕了,这是什么鬼?刚开始接触这种名词,反正我是有点摸不着头脑,略抽象,很差理解。函数
那放下这术语无论,先看看为何要用它。性能
页面事件中,scroll, resize 和 mousemove 事件都有一个共同点,就是会频繁地被触发。举个例子,那 scroll 来看好了。ui
先写一段代码:spa
let num = 1
window.onscroll = () => {
console.log(num++)
}
复制代码
这里监听了页面的 scroll 事件,当页面滚动时,打印出递增的数字。3d
下图是运行结果,能够看到,console 里面疯狂输出: code
回想一下最经常使用的 click 事件,是否是老老实实,点一次,执行一次。而 scroll 呢,滚动一小段,好几回就去了。这里还好,不涉及到 DOM 操做,要是在 scroll 事件中处理 DOM 元素,那页面性能确定受到影响,笔记本风扇说不定随着滚动的页面呼呼做响,或者页面一卡一卡卡出心脏病。cdn
让它消停点的办法,就是让回调少执行几回。提到让疯狂执行的函数少执行几回,限制它的行为,“节流”这个概念是否是隐隐约约出现,再也不那么抽象了?就比如把水龙头关小一点,让水慢慢流。blog
怎么让这个函数慢慢流呢?
设想一下,页面一直在滚动,根本停不下来。这个时候,回调也一直在触发,噼里啪啦。
和它商量一下: “你能不能隔几秒执行一次?”
"隔几秒?"
"两百毫秒吧。"
节流函数就是给这种高频率触发的函数,规定一个时间间隔,就是这一次执行和下一次执行的时间间隔。
有点像游戏里面的技能冷却时间,放了技能,进入冷却时间,这期间,就算不停地点技能,也放不了,只能等冷却好,再放。
千言万语不如上代码:
const throttle = (func, ms = 200) => {
let prev = new Date().getTime()
return function(...args) {
let now = new Date().getTime()
if (now - prev >= ms) {
func()
prev = now
}
}
}
复制代码
这里的 throttle 函数接受一个函数 func
和一个毫秒数 ms
做为参数,返回一个函数。当返回的函数不停地被触发,只有知足两次触发间隔大于或者等于规定的毫秒数,传入的 func
才执行。
这个间隔是用时间戳来判断的。首先定义变量 prev
记录一个时间,在返回的函数中,取得它执行时的时间戳 now
,比较两个时间戳,假如间隔大于规定的毫秒数 ms
,就执行传入的 func
函数。
拿上面的例子再举个例子:
let num = 1
window.onscroll = throttle(()=> {console.log(num++)}, 2000)
复制代码
这里监听页面滚动事件,每两秒触发一次回调函数。以下所示(没有慢放):
固然,实际开发中,不会两秒一次这么夸张。这里只是为了更明显地观察到节流函数的做用。
节流函数为高频率触发的回调设定一个执行周期,减小对页面性能的损耗。
可用于 resize, scroll, mousemove 这些事件的回调函数。