美文网首页
多重优化的函数防抖

多重优化的函数防抖

作者: 临安linan | 来源:发表于2019-08-17 13:13 被阅读0次

防抖的原理: 为了避免事件频繁触发执行, 让事件只有在触发后 n 秒才执行, 假如 n 秒内重新触发了事件, 则刷新时间戳, 在下一个 n 秒后执行 使用方式大概是: dom.onmousemove = debounce(getUserAction, 1000);

基础版防抖: 输入指定时间, 实现防抖

function debounce(fn, time){
  let timer
  return function(){
    clearTimeout(timer)
    timer = setTimeout(fn, time)
  }
}

只要在 time 内重新触发了事件, 定时器就会被清除掉, 重新开启下一个。

改良版

上一版实现了基础代码, 但是还有些地方需要完善, 比如:

  1. this 指向被改变了, 需要保证 fn 内部的 this 指向触发元素本身

  2. 需要提供 event 对象
    这里为了保证 this, 采用箭头函数, 同时将 arguments 参数对象传入, 保证 event 对象可以获取到

function debounce(fn, time){
  let timer
  return function(){
    // 事件触发时这里的 this 指向的是元素
    let args = arguments  // 取出的参数对象里包含了 event 对象
    clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, time)
  }
}

立即执行

以上, 我们的防抖函数已经比较完备了
但是还可以添加一个需求使之更完善:
不要等到事件停止触发后才执行,我希望立刻执行函数,然后等到停止触发 n 秒后,才可以重新触发执行
这里用一个可选参数来决定是否要采取这种立即触发的模式

function debounce(fn, time, immediate){
  let timer
  return function(){
    let args = arguments
    clearTimeout(timer)

    if(immediate){  // 采取立即执行模式
      let callNow = !timer  // 只有 timer 为 falsy 值时, 才立即执行
      timer = setTimeout(()=>{
        timer = null  // 只要 time 时间不触发, 就把 timer 设为 null, 那么下一次就会直接执行了
      }, time)
      callNow && fn.apply(this, args)
    }

    else{  // 采取传统模式
      timer = setTimeout(() => {
        fn.apply(this, args)
      }, time)
    }
  }
}

思路剖析: 当传入第三个参数为 true 时, 开启立即执行模式, 第一次的时候 timer 肯定为 undefined, 这时候 callNow 为 true, 立即执行
与此同时, 给 timer 赋值定时器, 这时候 timer 就不是 falsy 值了, 如果马上再触发一次, !timer 为false, 不会马上执行
同时, timer 设置的定时器里, time 时间后就会把 timer 重置为 null, 但是每次触发都会清除这个定时器, 所以只要在 time 时间内不去触发, 再下次触发时, !timer 就会为 true, 就能立即执行了

要注意: 定时器返回给 timer 的是数字, 即使清除了定时器, timer 的值也不会被清除, 只有手动赋值才能让其为 falsy 值。

可取消

这里还可以再完善一下, 添加重置 debounce 函数的功能,
假如说 debounce 的时间间隔是 10 s, immediate 为 true, 我只有等 10 秒后才能重新触发事件
我希望有时能够立即重置防抖, 即回到立即执行的状态。
只需添加一个取消函数来重置 timer 即可

function debounce(fn, time, immediate){
  let timer
  var debounceFn = function(){
    let args = arguments
    clearTimeout(timer)

    if(immediate){
      let callNow = !timer
      timer = setTimeout(()=>{
        timer = null
      }, time)
      callNow && fn.apply(this, args)
    }

    else{
      timer = setTimeout(() => {
        fn.apply(this, args)
      }, time)
    }
  }
  debounceFn.reset = function(){  // 取消函数, 注意: 取消完后又恢复
    clearTimeout(timer)
    timer = null
  }
  return debounceFn
}

使用的时候需要这样使用

let debounced = debounce(fn, 1000)
dom.onmousemove = debounced
// 重置函数的使用方法
button.onclick = debounced.reset

参考: https://github.com/mqyqingfeng/Blog/issues/22

相关文章

  • 多重优化的函数防抖

    防抖的原理: 为了避免事件频繁触发执行, 让事件只有在触发后 n 秒才执行, 假如 n 秒内重新触发了事件, 则刷...

  • JavaScript:函数防抖与节流

    什么是函数防抖与节流? 函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段。 定义: 防抖: n 秒后在...

  • 函数防抖和函数节流

    函数防抖和函数节流 函数防抖和函数节流:是优化高频率执行的JavaScript代码的一种手段。常用于JavaScr...

  • 彻底弄懂函数防抖和函数节流

    函数防抖和节流 函数防抖和函数节流:是优化高频率执行的JavaScript代码的一种手段。常用于JavaScrip...

  • 什么是防抖和节流?哪里会用到?重点是什么?怎样实现源码?

    什么是防抖和节流? 函数的防抖和节流,都是优化高频率执行js代码的方法,具体来说:函数防抖:是在频繁触发的情况下,...

  • 函数防抖&函数节流

    什么是函数防抖 / 节流 函数防抖和函数节流:优化高频率执行js代码的一种手段,可以让被调用的函数在一次连续的高频...

  • 函数防抖防抖/节流

    众所周知,函数节流和函数防抖都是优化高频率执行js代码的一种方法,二者的区别及使用方法如下: 函数节流 函数防抖,...

  • js函数防抖和函数节流

    函数防抖和函数节流都是降低回调执行频率,节省计算资源。是前端优化性能的一种手段。 一、概念 1.函数防抖: 在事件...

  • 11-函数防抖

    1.什么是函数防抖[debounce]?函数防抖是优化高频率执行js代码的一种手段可以让被调用的函数在一次连续的高...

  • JavaScript 函数节流和函数防抖

    函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段。 函数节流 是一定时间内只执行一次。 函数防抖 函数...

网友评论

      本文标题:多重优化的函数防抖

      本文链接:https://www.haomeiwen.com/subject/igghsctx.html