折腾侠
技术教程

JavaScript 闭包详解:从原理到实战

闭包是 JavaScript 的基石之一。本文从闭包的定义、核心原理入手,通过数据封装、函数工厂、防抖函数等实战场景,深入讲解闭包的应用。同时分析常见陷阱,帮助你写出更优雅、更安全的 JavaScript 代码。

折腾侠
2026/03/24 发布
13约 2 分钟238 字 / 244 词00

JavaScript 闭包详解:从原理到实战

什么是闭包?

闭包是指函数能够记住并访问其定义时所在的词法作用域,即使该函数在其作用域之外执行。

核心原理

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

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

关键点INLINE_CODE_0 变量被内部函数引用,即使 INLINE_CODE_1 执行完毕,INLINE_CODE_2 也不会被垃圾回收。

实际应用场景

1. 数据封装与私有变量

JavaScript
function createBankAccount(initialBalance) {
  let balance = initialBalance;  // 私有
  
  return {
    deposit: function(amount) {
      balance += amount;
      return balance;
    },
    withdraw: function(amount) {
      if (amount > balance) throw new Error("余额不足");
      balance -= amount;
      return balance;
    },
    getBalance: function() {
      return balance;
    }
  };
}

const account = createBankAccount(1000);
account.deposit(500);  // 1500
account.withdraw(200); // 1300

2. 函数工厂

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

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

console.log(double(5)); // 10
console.log(triple(5)); // 15

3. 防抖函数(实用工具)

JavaScript
function debounce(func, delay) {
  let timeoutId;
  
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

// 使用:搜索框输入时延迟发送请求
const searchInput = document.getElementById("search");
searchInput.addEventListener("input", debounce((e) => {
  fetch(`/api/search?q=${e.target.value}`);
}, 300));

常见陷阱

JavaScript
// ❌ 错误:循环中的闭包
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// 输出:3, 3, 3(var 没有块级作用域)

// ✅ 正确:使用 let
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// 输出:0, 1, 2

总结

特性说明
本质函数 + 词法作用域
优势数据私有化、状态保持
注意避免内存泄漏,及时清理引用
适用模块化、回调、事件处理

闭包是 JavaScript 的基石之一,掌握它能让你写出更优雅、更安全的代码。

分享到:

如果这篇文章对你有帮助,欢迎请作者喝杯咖啡 ☕

加载评论中...