You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中防抖函数返回函数的触发机制解析

防抖函数内部返回函数的触发原理

问题描述

我编写了如下防抖函数代码:

const selectElement = document.querySelector('input');

const debounce = (cb, time = 1000) => {
  let timer;

  return (...args) => {
    console.log('run inner function')
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => cb(...args), time)
  }
}

const onChange = debounce((e) => {
  console.log('event', e.target.value)
})
selectElement.addEventListener('input', onChange);
<input input={onChange}/>

上述代码运行正常,但我想理解防抖函数内部返回的函数是如何被触发的。我了解通常返回函数的函数需要通过debounce()()的方式调用才能触发内部函数,但此处仅调用一次debounce()得到onChange并传入addEventListener,内部函数却能执行,希望知晓其中原理。


原理解析

  1. debounce是高阶函数,返回的是一个函数
    调用debounce((e) => {...})时,并不会执行内部那个带console.log('run inner function')的箭头函数,而是直接把这个箭头函数作为返回值赋值给了onChange变量。此时onChange就是那个内部返回的函数本身。

  2. addEventListener会自动调用传入的函数
    addEventListener('input', onChange)的作用是:告诉浏览器——当input元素触发input事件时,去调用onChange这个函数。所以当你在输入框输入内容时,浏览器会自动执行onChange(e)(这里的e是事件对象),这就触发了防抖函数返回的内部函数。

  3. 和手动调用的区别
    你之前理解的debounce()()是手动触发内部函数:第一次调用debounce()拿到返回的函数,第二次括号是手动执行它。而这里是把返回的函数交给了浏览器的事件系统,由事件系统在合适的时机自动执行它,本质上和你手动写onChange()是一样的,只是调用的主体从你变成了浏览器。

举个极简例子辅助理解:

// 一个返回函数的函数
const outer = () => {
  return () => console.log('内部函数执行了')
}
// 拿到内部函数
const inner = outer()
// 手动调用内部函数
inner() // 打印"内部函数执行了"
// 或者把inner传给事件监听,由浏览器调用
document.querySelector('button').addEventListener('click', inner)
// 点击按钮时,浏览器会自动调用inner(),同样打印内容

内容的提问来源于stack exchange,提问作者Asking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:05:15