防抖和节流的实现
防抖和节流,在日常的开发过程中会经常用到,而在面试中,也是经常会被问的一道手写题。下面就一起复习一下这两个函数的知识点和实现吧。
知识点
在工作中常见的一些场景,比如input搜索框、监听窗口的resize,元素的拖拽,以及滚动条的监听。这些场景的共同点就是事件会被频繁的触发,而频繁的触发会导致资源和性能的大量消耗。通常我们会使用防抖和节流函数来进行优化,那么什么场景该使用防抖,什么时候该使用节流呢?
共同点 | 区别 | 应用场景 | |
---|---|---|---|
防抖debounce | 在事件频繁被触发时, | 只执行最后一次 | input输入框、窗口resize、button点击 |
节流throttle | 减少事件执行的次数 | 有规律的执行 | 拖拽、scroll |
防抖debounce实现
通过知识点我们可以知道,防抖函数的作用是在事件被频繁触发时,只执行最后一次。本质上是延迟执行事件的时机,那么我们可以利用定时器来实现它。
1 |
|
上面的代码看似没啥毛病,但实际每次执行的时候,timer都会被重新创建,然后执行完debounce后,里面的变量就会被销毁。这样就会创建出很多个延迟没执行的函数,一到时间就执行了,并不会重新计算时间。
那我们改造一下,把timer提到全局作用域内:
1 |
|
通过改造函数虽然也能实现防抖的功能,但是如果有多个防抖的事件,就需要定义多个全局变量,写多个函数,显然这并不是一个靠谱的实现。这时我们需要一个私有变量,并且能在外部访问,那闭包就是一个选择,我们接着改造:
1 |
|
调用debounce函数时,返回了一个匿名函数,由于该函数中还用到了debounce函数中的timer变量,会导致timer无法释放。这样就创建了一个私有变量并可以在外部进行访问。需要注意的是:在合适的时机对闭包进行清除,否则会一直占用内存。
节流throttle实现
同样的原理,只需稍作修改就可以实现节流throttle函数:
1 |
|
与防抖函数不同的是,节流函数是按一定频率有规律的执行,那么除了定时器以外,是不是还可以用时间差的方式来实现呢?
1 |
|
小结
防抖和节流函数,我们只需要掌握它的异同点、实现原理、应用场景即可,工作中通常不需要我们去重复的造轮子。有诸如Loadsh这种现成的开源工具,可以很方便的调用。