防抖(Debounce)是一种常用于限制连续触发事件的执行频率的技术。防抖的核心思想是在一定时间内只执行一次,如果在指定时间内再次触发,就重新计时。这在处理一些频繁触发的事件(如输入框输入、窗口大小变化等)时非常有用。
以下是一个简单的 JavaScript 防抖函数的实现,这个防抖函数接受三个参数:
- func:要执行的函数
- wait:等待的时间间隔
- immediate:是否立即执行
function debounce(func, wait = 100, options = {}) {
if (typeof func !== 'function') {
throw new TypeError(`Expected the first parameter to be a function, got \`${typeof func}\`.`)
}
if (wait < 0) {
throw new RangeError('`wait` must not be negative.')
}
const { immediate } = typeof options === 'boolean' ? { immediate: options } : options
let storedContext
let storedArguments
let timeoutId
let result
let timestamp
function later() {
const last = Date.now() - timestamp
if (last < wait && last >= 0) {
timeoutId = setTimeout(later, wait - last)
} else {
timeoutId = undefined
if (!immediate) {
result = func.apply(storedContext, storedArguments)
storedContext = undefined
storedArguments = undefined
}
}
}
const debounced = function (...args) {
if (storedContext && this !== storedContext) {
throw new Error('Debounced method called with different contexts.')
}
storedContext = this
storedArguments = args
timestamp = Date.now()
const callNow = immediate && !timeoutId
if (!timeoutId) {
timeoutId = setTimeout(later, wait)
}
if (callNow) {
result = func.apply(storedContext, storedArguments)
storedContext = undefined
storedArguments = undefined
}
return result
}
debounced.clear = () => {
if (timeoutId) {
clearTimeout(timeoutId)
timeoutId = undefined
}
}
debounced.flush = () => {
if (timeoutId) {
result = func.apply(storedContext, storedArguments)
storedContext = undefined
storedArguments = undefined
clearTimeout(timeoutId)
timeoutId = undefined
}
}
return debounced
}