闭包(Closure)


💡 闭包的概念

闭包 = 函数 + 函数定义时的作用域(环境)

更通俗的说法:

  • 当一个函数 能“记住”它定义时的环境,即使这个函数在别的地方执行,它也能访问那个环境里的变量。
  • 闭包就是 JS 的一种 变量私有化和长期记忆机制

🧩 类比生活场景

想象你在做 便签盒子

  1. 你写了一个便签,写上“今天做的事情”。
  2. 便签放进盒子里,盒子记住了便签上的内容。
  3. 以后你可以随时打开盒子,看到原来写的内容,即使你离开了写便签的地方。
  • 便签盒子 → 闭包
  • 便签内容 → 局部变量
  • 打开便签 → 执行函数访问变量

🔧 JS 示例

1️⃣ 简单闭包

function makeCounter() {
  let count = 0; // 局部变量,只有 makeCounter 内部可访问

  return function() {
    count++; // 内部函数可以访问外部函数的变量
    return count;
  };
}

const counter = makeCounter(); // 创建闭包
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

分析

  • makeCounter 执行一次,返回一个函数。
  • 返回的函数 记住了 count 这个变量,即使外部 makeCounter 已经执行完了。
  • 每次调用 counter() 都可以访问并修改 count

2️⃣ 闭包的私有变量

闭包可以实现 变量私有化,外部无法直接修改变量:

function createPerson(name) {
  let _name = name; // 私有变量

  return {
    getName: function() {
      return _name;
    },
    setName: function(newName) {
      _name = newName;
    }
  };
}

const person = createPerson("Logan");
console.log(person.getName()); // Logan
person.setName("Alice");
console.log(person.getName()); // Alice

分析

  • _name 对外部不可直接访问,只能通过 getNamesetName
  • 闭包帮我们安全地管理内部状态

3️⃣ 注意点

  1. 内存问题:闭包会让外部函数的局部变量一直存在,可能占用内存。
  2. 循环闭包陷阱
for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // 输出 3,3,3
  }, 100);
}

// 用 let 就不会了
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // 输出 0,1,2
  }, 100);
}
  • 因为 var 是函数级作用域,所有闭包共享同一个 i

💡 总结闭包的作用

  1. 访问外部函数的变量
  2. 实现私有变量和方法
  3. 保持函数执行环境(记忆功能)
  4. 在异步或回调中保持状态

常用英语介词固定搭配表(地点/时间/方向/方式)

JavaScript 的高级部分内容

评 论
请登录后再评论