全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 8 分钟 ✍️ juanwangdev

JavaScript 闭包

闭包是指函数能够访问其词法作用域,即使该函数在其作用域之外执行。

核心概念

JavaScript
function outer() {
  const message = 'Hello';

  function inner() {
    console.log(message);  // 访问外部变量
  }

  return inner;
}

const fn = outer();
fn();  // 'Hello' - 闭包保留了对 message 的引用

词法作用域

闭包基于词法作用域(静态作用域),函数定义时确定作用域:

JavaScript
const value = 'global';

function foo() {
  const value = 'local';
  return function() {
    console.log(value);  // 'local' - 定义时确定
  };
}

const fn = foo();
fn();  // 'local'

常见应用场景

数据私有化

JavaScript
function createCounter() {
  let count = 0;  // 私有变量

  return {
    increment() { return ++count; },
    decrement() { return --count; },
    getCount() { return count; }
  };
}

const counter = createCounter();
counter.increment();  // 1
counter.increment();  // 2
counter.getCount();   // 2
// count 不可直接访问

函数工厂

JavaScript
function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

double(5);   // 10
triple(5);   // 15

回调与事件处理

JavaScript
function setupButtons() {
  const buttons = document.querySelectorAll('button');

  buttons.forEach((button, index) => {
    button.addEventListener('click', () => {
      console.log(`Button ${index} clicked`);
    });
  });
}

偏函数应用

JavaScript
function fetch(url) {
  return function(path, options) {
    return fetch(`${url}${path}`, options);
  };
}

const apiFetch = fetch('https://api.example.com');
apiFetch('/users');  // https://api.example.com/users

循环中的闭包陷阱

问题代码

JavaScript
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);  // 输出: 3, 3, 3
  }, 100);
}

解决方案

JavaScript
// 方案1:使用 let(块级作用域)
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);  // 输出: 0, 1, 2
  }, 100);
}

// 方案2:IIFE 创建闭包
for (var i = 0; i < 3; i++) {
  ((j) => {
    setTimeout(() => {
      console.log(j);  // 输出: 0, 1, 2
    }, 100);
  })(i);
}

内存管理

闭包会保持对外部变量的引用,可能导致内存占用:

JavaScript
// 不好的做法:大对象被闭包持有
function process() {
  const largeData = new Array(1000000).fill('x');

  return function() {
    console.log(largeData.length);  // largeData 无法释放
  };
}

// 好的做法:只保留需要的数据
function process() {
  const largeData = new Array(1000000).fill('x');
  const length = largeData.length;
  // largeData 可被回收

  return function() {
    console.log(length);
  };
}

闭包 vs 作用域

概念说明
作用域变量的可访问范围
词法作用域定义时确定的作用域
闭包函数 + 其词法作用域

要点总结

  • 闭包允许函数访问定义时的外部变量
  • 用途:数据私有化、函数工厂、回调函数
  • 循环中使用 let 或 IIFE 避免闭包陷阱
  • 注意内存管理,避免持有不需要的数据
  • 闭包是函数式编程的基础机制

📝 发现内容有误?点击此处直接编辑

← 上一篇 返回值
下一篇 → JavaScript break 和 continue
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库