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,而不是全局的 messagesecond 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 4third 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