手写防抖函数

简介: JS查漏补缺系列是我在学习JS高级语法时做的笔记,通过实践费曼学习法进一步加深自己对其的理解,也希望别人能通过我的笔记能学习到相关的知识点。这一次我们来试着手写防抖函数

简单实现

<input type="text">
<script src="./01_debounce-v1-基本实现.js"></script>
<script>
  const inputEl = document.querySelector("input")
  let counter = 0

  const inputChange = function(event) {
    console.log(`发送了第${++counter}次网络请求`)
  }

  // 防抖处理
  inputEl.oninput = debounce(inputChange, 2000)
</script>
function debounce(fn, delay) {
  // 1.定义一个定时器, 保存上一次的定时器
  let timer = null

  // 2.真正执行的函数
  const _debounce = function() {
    // 取消上一次的定时器 
    // (不取消就会在最后一次性发送前面堆积的请求,而我们要实现的是到最后才请求一次)
    if (timer) clearTimeout(timer)
    // 延迟执行
    timer = setTimeout(() => {
      // 外部传入的真正要执行的函数
      fn()
    }, delay)
  }

  return _debounce
}

功能优化——this、参数改进

在原来的基础之上将inputChange修改了一下:

<script>
const inputChange = function(event) {
    console.log(`发送了第${++counter}次网络请求`,this,event)
}
</script>

直接用inputEl.oninput = inputChange触发得到:

用第三方库触发得到:
image.png
用我们上面手写的防抖函数得到:
image.png
可见的我们的函数对this和event的处理是有问题的。
改进:

function debounce(fn, delay) {
  let timer = null
  const _debounce = function(...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      // 用apply进行绑定this、arg
      fn.apply(this, args)
    }, delay)
  }

  return _debounce
}

功能优化——立即执行

:::info
功能实现:希望在第一次执行的时候就能给我立刻请求一次(可以选择立即执行/不立即执行)
:::
改进:

function debounce(fn, delay, immediate = false) {
  let timer = null
  let isInvoke = false

  const _debounce = function(...args) {
    if (timer) clearTimeout(timer)

    // 判断是否需要立即执行
    if (immediate && !isInvoke) {
      fn.apply(this, args)
      isInvoke = true 
    } else {
      timer = setTimeout(() => {
        fn.apply(this, args)
        isInvoke = false
      }, delay)
    }
  }

  return _debounce
}

功能优化——取消功能

:::info
场景:用户在输入东西之后防抖函数发送请求之前按到退出键退出了界面,这时我们就不用再发送请求
:::

<script>
// 取消功能
const cancelBtn = document.querySelector("#cancel")
cancelBtn.onclick = function() {
        debounceChange.cancel()
}
<script>
    // 封装取消功能
  _debounce.cancel = function() {
    if (timer) clearTimeout(timer)
    // 好习惯:取消或执行完毕后将默认值重置
    timer = null
    isInvoke = false
  }

功能优化——函数返回值

<script>
const inputChange = function(event) {
   console.log(`发送了第${++counter}次网络请求`, this, event)

   // 返回值
   return "aaaaaaaaaaaa"
}
  // 防抖处理
const debounceChange = debounce(inputChange, 3000, false, (res) => {
  console.log("拿到真正执行函数的返回值:", res)
})
</script>
function debounce(fn, delay, immediate = false, resultCallback) {
  let timer = null
  let isInvoke = false
  const _debounce = function(...args) {
      if (timer) clearTimeout(timer)
      if (immediate && !isInvoke) {
        const result = fn.apply(this, args)
        if (resultCallback) resultCallback(result)
        isInvoke = true
      } else {
        timer = setTimeout(() => {
          const result = fn.apply(this, args)
          if (resultCallback) resultCallback(result)
          isInvoke = false
          timer = null
        }, delay)
      }
    })
  }

  // 封装取消功能
  _debounce.cancel = function() {
    if (timer) clearTimeout(timer)
    timer = null
    isInvoke = false
  }

  return _debounce
}
目录
相关文章
|
5G 调度 UED
5G中的动态频谱共享(DSS):高效利用频谱资源,加速5G网络演进
5G中的动态频谱共享(DSS):高效利用频谱资源,加速5G网络演进
2638 4
|
Linux
Redhat 各版本与linux内核对应参照表
1、查看linux内核的版本号: [root@rac2 ~]# uname-aLinux rac22.6.18-194.el5 #1 SMP Tue Mar 16 21:52:43 EDT 2010 i686 i686 i386 GNU/LinuxYou...
2761 0
|
5天前
|
数据采集 人工智能 安全
|
15天前
|
云安全 监控 安全
|
1天前
|
存储 SQL 大数据
删库跑路?别慌!Time Travel 带你穿回昨天的数据世界
删库跑路?别慌!Time Travel 带你穿回昨天的数据世界
234 156
|
8天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
595 5