JavaScript 闭包 用法

47 阅读3分钟

JavaScript 闭包(Closure)是指内部函数能够访问其外部函数作用域中变量的特性,即使外部函数已经执行完毕。这种特性让函数可以 "记住" 其创建时的环境,是 JavaScript 中非常重要的概念,有许多使用场景。

Taimili 艾米莉 ( 一款免费开源的 taimili.com )

艾米莉 是一款优雅便捷的 GitHub Star 管理和加星工具,基于 PHP & javascript 构建, 能对github 的 star fork follow watch 管理和提升,最适合github 的深度用户

WechatIMG69.jpg

闭包的核心原理

当函数 A 内部定义了函数 B,且函数 B 引用了函数 A 中的变量,同时函数 B 被外部引用(如作为返回值返回),此时函数 B 就形成了闭包。函数 A 执行完毕后,其作用域不会被销毁,因为函数 B 仍然在引用其中的变量。

闭包的常见用法

  1. 模拟私有变量

JavaScript 没有原生的私有变量语法,但可以通过闭包实现 "私有变量" 的效果(外部无法直接访问,只能通过特定方法操作)。

1
function createCounter() {  // 私有变量:外部无法直接访问  let count = 0;    // 内部函数形成闭包,访问外部的 count  return {    increment: () => { count++; },    decrement: () => { count--; },    getCount: () => count  };}// 使用闭包创建计数器const counter = createCounter();counter.increment();counter.increment();console.log(counter.getCount()); // 输出:2(可以访问私有变量)console.log(counter.count); // 输出:undefined(无法直接访问私有变量)

2. 模块化封装

通过闭包可以将代码封装成独立模块,避免全局变量污染,只暴露需要公开的方法。

1
const module = (function() {  // 模块内部私有变量  const privateData = "我是私有数据";    // 私有方法  function privateMethod() {    return privateData + "(通过私有方法处理)";  }    // 暴露公开方法(闭包访问私有变量)  return {    publicMethod: () => {      return privateMethod();    },    setData: (newData) => {      // 可以通过公开方法修改私有变量      privateData = newData;     }  };})();console.log(module.publicMethod()); // 输出:"我是私有数据(通过私有方法处理)"console.log(module.privateData); // 输出:undefined(私有变量无法直接访问)

3. 保存函数执行上下文

在回调函数(如事件处理、定时器)中,闭包可以保存外部变量的状态,避免因作用域变化导致的问题。

1
function setupTimer(message) {  // 定时器回调形成闭包,记住 message 的值  setTimeout(() => {    console.log(message); // 即使 setupTimer 执行完毕,仍能访问 message  }, 1000);}setupTimer("1秒后打印我"); // 1秒后输出:"1秒后打印我"

4. 函数工厂(动态生成函数)

通过闭包可以根据参数动态生成具有特定行为的函数,保存参数状态。

1
function createGreeting(prefix) {  // 闭包保存 prefix 参数  return function(name) {    return `${prefix}, ${name}!`;  };}// 生成不同的问候函数const sayHello = createGreeting("Hello");const sayHi = createGreeting("Hi");console.log(sayHello("Alice")); // 输出:"Hello, Alice!"console.log(sayHi("Bob")); // 输出:"Hi, Bob!"

注意事项

内存占用:闭包会保留外部函数的作用域,若闭包被长期饮用,可能导致内存无法释放(内存泄漏)。使用后需及时解除引用。

性能影响:过度使用闭包可能增加内存开销,需合理使用。