什么是闭包

什么是闭包

闭包定义

在JavaScript中,内层函数引用外层函数作用域的变量/函数,且内层函数被外部访问,导致外层函数执行完后,其作用域不会被销毁,这种"函数+其关联的作用域"组合称为闭包。

核心特征:

  • 延长变量的生命周期;
  • 私有化变量(避免全局污染)。

核心示例

javascript 复制代码
function outer() {
  const privateVar = '私有变量'; // 外层函数变量
  // 内层函数引用外层变量
  function inner() {
    console.log(privateVar);
  }
  return inner; // 内层函数被外部访问
}

const fn = outer(); 
fn(); // 输出:私有变量(outer执行完后,privateVar仍被保留)

适用场景

  1. 私有化变量/方法:模拟类的私有属性(JavaScript无原生私有属性)。
javascript 复制代码
const Counter = (() => {
  let count = 0; // 私有变量,外部无法直接访问
  return {
    increment: () => count++,
    decrement: () => count--,
    getCount: () => count
  };
})();
Counter.increment();
console.log(Counter.getCount()); // 1
console.log(Counter.count); // undefined(无法直接访问)
  1. 缓存数据:如计算结果缓存(避免重复计算)。
javascript 复制代码
function createCalculator() {
  const cache = {}; // 缓存计算结果
  return {
    add: (a, b) => {
      const key = `${a}+${b}`;
      if (cache[key]) return cache[key];
      const result = a + b;
      cache[key] = result;
      return result;
    }
  };
}
const calc = createCalculator();
console.log(calc.add(1, 2)); // 3(计算并缓存)
console.log(calc.add(1, 2)); // 3(直接取缓存)
  1. 防抖/节流函数:依赖闭包保存定时器ID/触发时间。
javascript 复制代码
// 防抖函数(闭包实现)
function debounce(fn, delay) {
  let timer = null; // 闭包保存定时器ID
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}
// 节流函数(闭包实现)
function throttle(fn, interval) {
  let lastTime = 0; // 闭包保存上次执行时间
  return (...args) => {
    const now = Date.now();
    if (now - lastTime >= interval) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}
  1. 事件监听/回调:保留上下文变量。
javascript 复制代码
function bindEvent() {
  const btn = document.getElementById('btn');
  const msg = '点击成功'; // 闭包保留msg
  btn.addEventListener('click', () => {
    alert(msg);
  });
}
bindEvent();

注意事项

1.闭包会导致变量长期驻留内存,滥用可能导致内存泄漏(需手动释放,如将引用置为null)。

2.循环引用问题: 闭包与DOM元素互相引用可能导致内存泄漏。

3.数据元素遍历中,频繁创建闭包可能影响性能。

4.多层嵌套闭包导致作用域链查找变慢。

  1. 变量意外共享问题: 循环中创建闭包时的经典问题

相关推荐
kyriewen29 分钟前
我把 AI 写的并发请求控制器手写了一遍——3 个语义我当时根本讲不清
前端·javascript·面试
_codemonster1 小时前
Vue中的ref和reactive到底在干嘛
前端·javascript·vue.js
张元清2 小时前
React useEventListener Hook:类型安全的 DOM 事件监听 (2026)
javascript·react.js
weixin_461408582 小时前
npm npx yarn
开发语言·前端·javascript
四千岁2 小时前
RAG系统中的分块
前端·javascript·后端
进击的明明3 小时前
闭包:JavaScript里的“随身背包” 🎒
前端·javascript·面试
我会冲击波5 小时前
vibe coding 一个多月,我把 Claude Code + Pi 做成了桌面 IDE,还给它移植了 VS Code 的编辑体验
前端·javascript·后端
码艺-Alimjan5 小时前
横向滚动组件纯用 CSS,丝滑鼠标滚动不许js
javascript·css·计算机外设
JimmtButler6 小时前
从 Java 到 JS:我终于把闭包想明白了
javascript·后端
常宇佳6 小时前
vue3 实战系列之无法识别vue组件
前端·javascript·vue.js