什么是闭包

什么是闭包

闭包定义

在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. 变量意外共享问题: 循环中创建闭包时的经典问题

相关推荐
默_笙2 小时前
🍕 AI 的嘴巴装了水管(上):从"等它说完"到"边说边听"的流式输出指南
前端·javascript
暖焰核心2 小时前
继承全解——继承、默认成员函数、切片、隐藏与虚继承
java·前端·javascript
艾伦野鸽ggg2 小时前
前端异步请求的状态竞争(请求竞态)问题
前端·javascript·axios
是立不是利3 小时前
前端交互基石:深入剖析JavaScript三级联动背后的设计哲学
开发语言·前端·javascript
老刘的望远镜3 小时前
AgentScope Java 从零(03):Agent 的记性默认全开,我在第 50 轮翻了车
java·开发语言·javascript
前端精髓3 小时前
React 更新 state 中的对象
javascript·react.js·ecmascript
可乐鸡翅yeah_4 小时前
hls.js 播放质量埋点实战,采集卡顿、起播、错误指标定位线上用户问题
开发语言·前端·javascript·ecmascript·音视频·m3u8·音视频在线播放
Bs_MoneyMagnet6 小时前
基于springboot+vue的宠物殡葬管理平台的设计与实现 源码+文档
java·javascript·vue.js·spring boot·后端·宠物
尾善爱看海7 小时前
Vue 面试进阶篇:Composition API、插槽、自定义指令……8 个章节 + 高频面试题全解析
前端·javascript·vue.js·面试·vue
三小河8 小时前
在 Codex 桌面端接入 DeepSeek 模型(CC Switch 代理中转)
前端·javascript·人工智能