let debouce = function(func, wait, immediate) {
let timer = null
return function(...args) {
let self = this
if (immediate && !timer) func.call(self, ...args)
clearTimeout(timer)
timer = setTimeout(function() {
if (!immediate) func.call(self, ...args)
timer = null
// 在 immediate 为 false 的时候, timer = null 对其没有影响
}, wait)
}
}
2. 节流
在一个时间段内, 无论触发多少次事件, 最终只会执行一次回调函数
如图所示, 在 wait 时间段内, 只会在 first trigger 时执行回调函数, 而在 after triggers 时则不会执行回调函数
2.1 throttle 的初步实现
let throttle = function(func, wait) {
let previous = 0
// 上一次执行回调函数的时间
return function(...args) {
let now = +new Date()
if (now - previous > wait) {
func.call(this, ...args)
previous = now
// 更新上一次触发事件的时间
}
}
}
2.2 throttle 的进一步实现
对照上图, 如果在 wait 时间段中已经有了 first trigger 的前提下, 还有一堆的 after triggers, 则这些 after triggers 中最后一个(记作 a)则会延迟到下一个 wait 时间段(记作 next_wait)作为 first trigger 触发
然而若是在 next_wait 的开始就有一个 first trigger(记作 b), 则会执行 b 而不执行 a
let throttle = function(func, wait) {
let previous = 0
// 上一次执行回调函数的时间
let timer = null
return function(...args) {
let now = +new Date()
let remaining = wait - (now - previous)
// 触发事件时, 距离下一个 wait 的时间
if (remaining <= 0) {
func.call(this, ...args)
previous = now
clearTimeout(timer)
// 防止在 b 执行后执行 a
} else {
// 如果还没到下一个时间段, 则使用计时器, 待到下一个时间段时执行回调函数
clearTimeout(timer)
timer = setTimeout(function() {
func.call(this, ...args)
previous = +new Date()
}, remaining)
}
}
}
1. 防抖
对于频繁触发的事件, 如果浏览器也频繁的响应, 则会占用大量的进程资源, 导致卡顿. 而防抖就是为了防止浏览器因事件的频繁触发而频繁响应
原理: 对于一个触发的事件, 会在 n ms 后调用其回调函数, 如果这个事件在短时间内频繁触发, 则会在最后一次触发该事件时计时, 待 n ms 后执行回调函数
1.1 debounce 的初步实现
1.2 debounce 的进一步实现
然而有时候, 我们需要在第一次点击的时候就立即执行回调函数
1.3 debounce 的代码简化
2. 节流
在一个时间段内, 无论触发多少次事件, 最终只会执行一次回调函数 如图所示, 在 wait 时间段内, 只会在 first trigger 时执行回调函数, 而在 after triggers 时则不会执行回调函数
2.1 throttle 的初步实现
2.2 throttle 的进一步实现
对照上图, 如果在 wait 时间段中已经有了 first trigger 的前提下, 还有一堆的 after triggers, 则这些 after triggers 中最后一个(记作 a)则会延迟到下一个 wait 时间段(记作 next_wait)作为 first trigger 触发 然而若是在 next_wait 的开始就有一个 first trigger(记作 b), 则会执行 b 而不执行 a