closure = a function defined inside of another function, the inner function has access to the variables and scope of the outer function

  • Allow for private variables and state maintenance
  • Used frequently in JS frameworks: React, Vue, Angular
// ======================== 闭包 (Closure) 示例 ========================
 
function outer(){   // 外层函数(outer scope)
  
  // 局部变量(只属于 outer 函数作用域)
  let message = "hello";
  
  // 内层函数(inner)定义在 outer 里面
  function inner(){
    // 这里访问了外层函数的变量 message
    // 这就形成了“闭包”(inner 函数记住了外层作用域中的变量)
    console.log(message);
  }
  
  // 调用内层函数
  inner();
}
 
// 这里定义了一个全局变量 message
// ⚠️ 注意:它与 outer() 内部的 message 是两个不同作用域的变量
message = "goodbye";
 
// 调用外层函数
outer(); 
// 输出:hello
// 因为 inner() 访问的是 outer() 作用域内的 message,而不是全局的 message

second example

// ======================== 闭包应用:计数器 (Counter) ========================
 
// 定义一个函数 createCounter,用来创建“计数器”对象
function createCounter(){
  // 局部变量 count —— 只在 createCounter() 作用域中存在
  // 外部无法直接访问
  let count = 0;
 
  // 定义内部函数 increment,用于增加 count 的值
  function increment(){
    count++;  // 每次调用时让 count 加 1
    console.log(`count increased to ${count}`);
  }
  
  // 定义内部函数 getCount,用于获取当前 count 的值
  function getCount(){
    return count;
  }
  
  // 返回一个对象,包含两个可以被外部访问的函数
  // 注意:外部无法直接访问 count,只能通过这两个函数间接操作
  return { increment, getCount };
}
 
// ======================== 使用计数器 ========================
 
// 调用 createCounter() 会创建一个新的闭包
// 此时内部的 count 变量被“封装”在闭包环境中
const counter = createCounter();
 
// 多次调用 increment(),每次都会访问同一个闭包中的 count 变量
counter.increment(); // 输出: count increased to 1
counter.increment(); // 输出: count increased to 2
counter.increment(); // 输出: count increased to 3
counter.increment(); // 输出: count increased to 4
 
// 使用 getCount() 获取当前计数值
console.log(`current count is ${counter.getCount()}`);
// 输出: current count is 4

third example

// ======================== 闭包应用:游戏得分系统 ========================
 
// 定义一个函数 createGame,用来创建一个“游戏得分对象”
function createGame(){
 
  // 局部变量 score —— 保存当前分数
  // 它只存在于 createGame() 的作用域中
  // 外部无法直接访问,只能通过内部函数操作
  let score = 0;
 
  // ------------------ 内部函数 1:增加分数 ------------------
  // points 是传入的得分数值
  function increaseScore(points){
    score += points;  // 在闭包中修改 score 的值
    console.log(`+${points}pts`); // 输出加分提示
  }
  
  // ------------------ 内部函数 2:减少分数 ------------------
  function decreaseScore(points){
    score -= points;  // 在闭包中修改 score 的值
    console.log(`-${points}pts`); // 输出减分提示
  }
  
  // ------------------ 内部函数 3:获取当前分数 ------------------
  function getScore(){
    return score;  // 返回当前分数
  }
  
  // 返回一个对象,暴露三个可以操作分数的接口
  // 但不暴露 score 变量本身,从而实现“数据封装”
  return {
    increaseScore, 
    decreaseScore, 
    getScore
  };
}
 
// ======================== 使用示例 ========================
 
// 调用 createGame() 会创建一个新的“游戏实例”
// 内部的 score 被保存在闭包中(不会被外部直接修改)
const game = createGame();
 
// 调用闭包函数修改分数
game.increaseScore(5);  // 输出: +5pts   → score = 5
game.increaseScore(6);  // 输出: +6pts   → score = 11
game.decreaseScore(3);  // 输出: -3pts   → score = 8
 
// 获取最终得分
console.log(`final score is: ${game.getScore()}`);
// 输出: final score is: 8