- 为什么需要防抖和节流:在高频率事件触发的场景下,不希望对应的事件处理函数被瞬间多次执行
- 场景举例:点击操作,滚动事件,输入框的模糊匹配,轮播图点击切换 等等
- chrome默认监听事件的间隔4~6ms,如果检测到多次事件监听并执行,会造成不必要的资源浪费
防抖函数
/**
*
* @param {Function} handle
* @param {Int} tick
* @param {Boolean} immediate
* @returns
*/
function myDebounce(handle, tick, immediate) {
let initTick = 300
if (typeof handle !== 'function') new Error('handle must be an function')
if (typeof tick === 'boolean') {
immediate = tick
tick = initTick
}
if (typeof tick === 'undefined') tick = initTick
if (typeof immediate !== 'boolean') immediate = false
let timer = null
return function (...args) {
let self = this, init = immediate && !timer
clearTimeout(timer)
timer = setTimeout(() => {
if (!immediate) handle.call(self, ...args)
timer = null
}, tick);
if (init) handle.call(self, ...args)
}
}
handle 参数为最终执行的监听事件。
tick 参数为期望事件触发的时间刻度,默认300,可以在函数内修改(300ms之内不会触发监听的事件)
immediate 参数为boolean,true时,响应第一次触发的监听事件。false时,响应最后一次
在Html中高频点击按钮触发click事件的测试:
<button id="btn"> 按钮1 </button>
var btn = document.getElementById('btn')
btn.onclick = myDebounce(function (event) {
console.log('点击了', this, event)
}, 400, false)
节流函数
/**
*
* @param {Function} handle
* @param {Int} wait
* @returns
*/
function myThrottle(handle, wait = 300) {
if (typeof handle !== 'function') new Error('handle must be an function')
let previous = 0
let timer = null
return function (...args) {
let now = new Date()
let self = this
let interval = wait - (now - previous)
if (interval <= 0) {
clearInterval(timer)
timer = null
handle.call(self, ...args)
previous = new Date()
} else if (!timer) {
timer = setTimeout(() => {
clearInterval(timer)
timer = null
handle.call(self, ...args)
previous = new Date()
}, interval);
}
}
}
handle 参数为最终执行的监听事件。
wait 参数为等待多少毫秒之后触发事件,以达到节流的目的