手写一个防抖函数
-
什么是防抖函数: 防抖函数是指在某个函数,某段时间内,无论触发的多少次,都只执行最后一次,并且每次调用函数都重新开始计时,无论这个函数有没有调用成功,直到时间间隔内,没有调用过函数请求
-
原理和实现:利用定时器,函数第一次执行时设定一个定时器,之后调用时发现,已经设定过定时器,就清空之前的定时器,重新设定一个定时器,如果存在没有被清空的定时器,当定时器计时结束后出发函数执行。
// 实现1 /** * @description 防抖函数 * @param { Function } fn: 时间到时要执行的回调函数 * @param { number } wait: 时间间隔 默认值为1000ms */ function debounce(fn, wait = 1000) => { // 闭包外层产生一个 定时器id let timer = null; return function (...args){ // 再次出发 如果存在定时器,就清除定时器 if(timer) clearTimeout(timer); // 并且重新设置一个定时器,也就是说,如果触发了函数,就会继续延长时间间隔,直到中间没有触发过 timer = setTimeou(() => { fn.apply(this, args) }, wait) } } // DEMO // 执行 debounce 函数返回新函数 const betterFn = debounce(() => console.log('fn 防抖执行了'), 1000) // 停止滑动 1 秒后执行函数 () => console.log('fn 防抖执行了') document.addEventListener('scroll', betterFn) // es6 const debounce = (fn, wait = 1000 ) => { let timer = null; return (...args) => { if(timer) clearTimeout(timer); timer = setTimeout(() => { fn(...args); }, wait) } } // DEMO // 执行 debounce 函数返回新函数 const betterFn = debounce(() => console.log('fn 防抖执行了'), 1000) // 停止滑动 1 秒后执行函数 () => console.log('fn 防抖执行了') document.addEventListener('scroll', betterFn); // 上面基本上满足了所有的要求了, 但是还可以优化,比如我第一次调用的时候,需要触发,不要等待 // 实现2 /** * @description 防抖函数 * @param { Function } fn: 时间到时要执行的回调函数 * @param { number } wait: 时间间隔 默认值为1000ms * @param { boolean } immediate: 是否第一次就触发回调函数 */ // 实现 2 // immediate 表示第一次是否立即执行 function debounce(fn, wait = 50, immediate) { let timer = null return function(...args) { if (timer) clearTimeout(timer) // ------ 新增部分 start ------ // immediate 为 true 表示第一次触发后执行 // timer 为空表示首次触发 if (immediate && !timer) { fn.apply(this, args) } // ------ 新增部分 end ------ timer = setTimeout(() => { fn.apply(this, args) }, wait) } } // DEMO // 执行 debounce 函数返回新函数 const betterFn = debounce(() => console.log('fn 防抖执行了'), 1000, true) // 第一次触发 scroll 执行一次 fn,后续只有在停止滑动 1 秒后才执行函数 fn document.addEventListener('scroll', betterFn) // es6 function debounce(fn, wait = 1000, immediate){ let timer = null; return (...args) => { if (timer) clearTimeout(timer); // 只有第一次的时候,这个值才管用,因为只有第一次的时候, 是没有定时器了 // 因为就算函数执行之后,这个定时器也是没有被销毁的 if (immediate && !timer){ fn(...args) } timer = setTimeout(() => { fn(...args) }, wait) } } // DEMO // 执行 debounce 函数返回新函数 const betterFn = debounce(() => console.log('fn 防抖执行了'), 1000, true) // 第一次触发 scroll 执行一次 fn,后续只有在停止滑动 1 秒后才执行函数 fn document.addEventListener('scroll', betterFn)