函数节流与函数防抖
最近由于处于互联网大厂的秋招季节,因此这些天都在看前端性能优化和算法方面的知识。在性能优化方面,看了网上的一些文章,同时看完了《高性能网站建设指南》和《高性能JavaScript》两本书,颇有收获,可以参看这篇文章,主要是一些前端性能优化方面的总结。传送门:前端性能优化最佳实践
这篇文章主要是讲函数节流与函数防抖相关知识的。虽然在上面两本书里面没有谈及这两方面的内容,但是我觉得,对JS常用事件进行节流或者防抖的处理是属于性能优化方面的。
目的
实现了这两个功能函数之后发现,节流同防抖在实现过程可能不太一样,但是目的和本质都是一样的:提高性能
相同点
节流和防抖都是采用闭包的形式来实现。这主要运用了闭包的一个特性:能够记住并访问所在的词法作用的标识符。如果对闭包不了解的可以看看这个回答:什么是闭包
用途
假如,一条河流,想检测水质问题。那么我们可以完全堵住,在某个时间段后,一次性释放。那么这些水就属于检测通过了。(这个比喻我都很迷... )
函数防抖也是大同小异。在某个特定时间后执行函数,但是在此时间段内重复调用函数的话,不会执行。只有当用户停下操作后,才会在该时间后执行此函数。
主要用于输入框keyup事件等一些需要用户输入内容的行为。
函数防抖
function debounce (fn, wait) {
let timer = null
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
timer = null
fn.apply(this, arguments)
}, wait)
}
}
函数节流
最简单的比喻,河流的水,如果想控制一下流量,那就可以让水流间隔的流。有点类似函数节流,间隔执行;如果完全堵住,在某个时间段后一次性释放,就是函数防抖了。
最简单的函数节流实现方式如下
function throttle (fn, wait) {
let start = 0
return function () {
const curr = Date.now()
if (curr - start < wait) return
start = curr
fn.apply(fn, arguments)
}
}
假如想加一些立即执行、多少秒后必须执行,那么可以参考下面的函数
function throttle (fn, option) {
let time = null
let start = null
let setting = {
delay: 300,
mustRunTime: 500, // 在500内必须执行。如在resize事件时,按住不放超过500ms之后就必须执行函数。
immediate: false
}
option = Object.assign({}, setting, option)
return function () {
let args = arguments
let context = this
let currStart = +new Date()
if (!start) {
start = currStart
}
let timeDiff = currStart - start
// 初始调用resise函数时立即执行函数,而不用等待delay的时间
if (option.immediate || timeDiff > option.mustRunTime || timeDiff > option.delay) {
fn.apply(context, args)
option.immediate = false
start = currStart
} else {
window.clearTimeout(time)
time = window.setTimeout(() => {
fn.apply(context, args)
}, option.delay)
}
}
}
最后
最后超简单总结下:
函数节流:间隔执行函数,主要用于keyup事件。
函数防抖:某个时间内都不执行,该时间后才执行函数,主要用于touchmove, resize等事件。