JS之节流和防抖

概述

在平时的开发中,常常会听到两个差很少很相近的词。节流(throttle)和防抖(debounce)。这是两个相似又有些不一样的优化方案。react

节流:在指定时间以内,让函数只触发一次。
防抖:对于必定时间段的连续的函数调用,只让其执行一次。ajax

两个方法在underscore.js中都已经实现了。本文将会重点说明两个函数的应用场景和背后的原理。浏览器

应用场景

节流

throttle在英语里的意思是节流阀,顾名思义,设置一个阀值(制定一个时间),在这个阀值或者时间以内,函数只会执行一次。闭包

举个例子,咱们执行页面滚动的时候,好比在react里面,可能每次滚动都会触发一次render,这样严重影响性能,甚至会形成浏览器卡死。若是咱们设置一个300ms的时间阀,那么在这段时间内,滚动时候只会触发一次render.app

一样的,当咱们拖拽某个元素的时候,会每次判断mousemove时跟位置相关的信息,每次都会执行相关的计算和判断,这种状况就和滚动时候同样,若是设置一个时间阀,那么就能够避免因为大量执行事件计算而形成的性能降低。函数

防抖

我本身的理解,防抖的意思能够认为是,阻止连续的抖动(所谓的事件触发),也就是说,咱们用防抖来让那些连续触发的事件只触发一次。性能

好比,当咱们对一个文本框进行输入的时候,在react中,每次都会触发onChange事件,咱们可能在每次事件里发送ajax请求,判断输入的用户名是否曾经注册过,这种状况下咱们使用防抖,能够保证只会在最后一次onChange事件才会触发ajax请求。优化

实现原理

节流this

节流实现起来很好理解,设置一个bool值,在时间阀以内,根据这个bool来判断是否执行函数。code

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函数来对频繁触发的事件进行控制和优化。