简洁的代码,详细的解释,每个前端er都要会的手写防抖功能。

本文详述了JavaScript防抖功能的实现,包括代码实现、形参解析、闭包和延迟定时器的运用,以及如何取消函数执行。通过实例探讨了防抖在前端开发中的应用,特别强调了立即执行和周期内交互的处理策略。

前言

又是一年的金三银四,疯狂的手写剧情再度上演,接下来就让我们一起来实现下JavaScript的防抖功能。

一、代码实现

本篇文章主要讲解防抖的实现,所以这里对于防抖的原理不做解释。相信想要搜索代码实现的你已经对防抖有着一定的理解。

const debounce = (fn, wait, immediate = false) => {
  let timer = null
  let hasInvoke = false
  return function (...args) {

    function run() {
      fn.apply(this, args)
      hasInvoke = true
    }

    function set() {
      timer = setTimeout(() => {
        !immediate && run()
        timer = null
        hasInvoke = false
      }, wait)
    }

    function reset() {
      clearTimeout(timer)
      set()
    }

    immediate && !hasInvoke && run()

    timer ? reset() : set()

  }
}

二、代码详解

2.1 防抖函数的形参

const debounce = (fn, wait, immediate = false) => {
  ... ...
}
  1. fn:需要进行防抖处理的目标函数。
  2. wait:延迟执行的时间(防抖时间周期)。
  3. immediate:是否在周期开始时立即调用目标函数。

2.2 自由变量的定义

let timer = null // 声明一个实现延迟执行的定时器
let hasInvoke = false // 对目标函数是否已经调用执行做一个标记

2.3 闭包函数(防抖的实现)

2.3.1 立即执行
function run() {
  fn.apply(this, args)
  hasInvoke = true
}
immediate && !hasInvoke && run()

本段代码就是立即执行的实现,如果需要立即执行(immediate = true)并且目标函数没有调用过则调用目标函数。

假设这里没有做目标函数是否调用的标记,用户在周期内再次做交互时,就会因为立即执行的原因使函数再次执行,无法实现防抖的目的。

2.3.2 延迟定时器的设置
function set() {
  timer = setTimeout(() => {
    !immediate && run()
    timer = null
    hasInvoke = false
  }, wait)
}

function reset() {
  clearTimeout(timer)
  set()
}

timer ? reset() : set()

判断用户在周期内是否已经进行过交互调用函数,即timer是否已经存在,如果存在需要对延迟定时器进行重置操作。反之如果是周期内第一次交互就直接设置一个新的延迟定时器。

设置定时器函数(function set)内需要判断是否为前缘防抖(立即执行模式),不是前缘防抖才需要在周期结束时进行目标函数的执行。

在周期结束时对timer进行一个null操作,进行内存的释放。当然此步骤也可以省略,因为在周期结束后,闭包函数对自由变量timer引用也会消失所以GC也可以正常回收timer。(这里理解的不知道对不对,希望大佬指点迷津。)

最后对是否调用标识设置为false,整个周期结束,目标函数被正常执行,所以相当于此次的防抖工作结束。下次重新开始时目标函数的状态为未被调用。

2.4 取消函数的执行

以上代码没有实现取消操作,如果想要在周期内对等待执行的目标函数取消执行,只需要利用clearTimeout对timer进行清理就可以了。这里就不做代码实现了,如果有需要的小伙伴可以自己尝试实现。

结语

其实不难发现,在防抖功能的实现过程中主要是利用了闭包,在周期内对定时器进行重置的过程。

以上就是手写防抖功能的实现过程,一个出自js小白的学习记录,不对的地方欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值