返回文章列表
frontend2026年1月6日约 2 分钟阅读

闭包到防抖&节流

准备 JS 八股的时候发现,闭包的实际应用场景主要集中在防抖、节流,因此我把这些内容统一整理在一起,从闭包本身出发去理解它们。

闭包

函数能够访问并记住其词法作用域,即使该函数在其定义作用域之外执行

function add() {
  let count = 0;
  return function () {
    count++;
    return count;
  };
}
 
const counter = add();
 
counter(); // 1
counter(); // 2
counter(); // 3

add 执行后本应销毁内部的 count ,但由于返回的内部函数 引用了 count ,count 被保存在闭包中,得以在多次调用中持续累加 :闭包 👉 在多次函数调用之间共享和保存状态

防抖 & 节流

防抖和节流都是一种优化手段,用来保证程序应对高并发场景,两者的核心目标都是:在高频触发的场景下,控制函数的执行时机。

防抖

就是即使操作多次触发,但是我们只处理最后一次,可以把防抖理解为:只要你还在操作,我就不执行;等你停下来一段时间,我再执行。

防抖常见于以下场景:

  • 搜索框输入联想
  • 输入校验
  • resize 事件

resize 是浏览器的一个 窗口尺寸变化事件。

当用户进行以下操作时,都会触发 resize:

  • 拖动浏览器窗口大小
  • 最大化 / 还原窗口
  • 改变设备方向(移动端横竖屏切换)
  • 改变视口大小(如 DevTools 打开/关闭)
function debounce(fn, delay) {
  // 准备一个“取消执行”的开关
  let timer = null;
 
  return function (...args) {
    // 每次触发都先取消上一次
    clearTimeout(timer);
 
    // 重新约定:delay 之后再执行
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}
const debouncedFn = debounce(search, 300);
//触发 → 清除定时器
//触发 → 清除定时器
//触发 → 清除定时器
//停止操作 → 执行函数

节流

事件可以一直触发,但函数按固定频率执行

节流通常用于:

  • 页面滚动(scroll)
  • 拖拽(drag)
  • 高频点击
function throttle(fn, delay) {
  let timer = null;
 
	  return function (...args) {
	  if (timer) return;
	
	  timer = setTimeout(() => {
	    // 保持原本的 this 和参数
	    fn.apply(this, args);
	    // 释放锁
	    timer = null;
	  }, delay);
	};
}
const throttled = throttle(fn, 1000);
目录 · 收起