聊聊闭包(以JS为例)

135 阅读6分钟

前言

这篇文章是本人对闭包的心得,希望可以帮助到大家,感谢大家的观看,如有错误欢迎大家指正

1.闭包是什么

闭包(Closure)是JavaScript中一个非常重要的概念,它指的是一个函数能够访问其创建时的作用域中的变量,即使这个函数在其原始作用域之外被调用。简单来说,闭包允许函数访问并操作外部函数的变量。

让我们用更通俗的语言来聊聊闭包。

想象一下,你有一个私人图书馆,这个图书馆有书和一些阅读灯。每次你进入图书馆,你都会打开灯,然后开始阅读。当你离开图书馆时,你关上灯,但图书馆里的书籍和灯光设置(比如亮度)都保持原样,等待你下次回来。

在编程中,闭包就像是这样一个私人图书馆:

  1. 私人空间:闭包提供了一个私人空间,在这个空间里,你可以存储一些只属于这个空间的数据,就像图书馆里的书籍和灯光设置一样。
  2. 记忆功能:当你离开图书馆时,图书馆记得你上次阅读的书和灯光的亮度。下次你回来,一切都还是你离开时的样子。同样,闭包可以记住它创建时的环境,即使那个环境已经结束了。
  3. 个人定制:你可以根据自己的喜好设置图书馆的灯光亮度,这些设置只对你有效。在编程中,闭包可以根据不同的情况定制化行为。
  4. 保护隐私:图书馆里的书籍和设置不会被其他人看到或改变,除非你带他们进来。闭包也可以保护数据不被外部直接访问或修改。
  5. 随时回来:无论你离开图书馆多久,只要你回来,一切都还是你离开时的样子。闭包可以在任何时候被调用,它都会记得之前的状态。

                                                 私人定制,爽!!!

2.闭包的特性

闭包的这些特性使得它在JavaScript编程中非常有用,但同时也需要注意它们可能导致的内存泄漏问题,因为闭包会持续引用外部变量,如果不正确管理,可能会导致内存泄漏。

  1. 闭包的特性是它在JavaScript中非常强大和有用的几个关键原因。以下是闭包的一些主要特性:
  2. 数据封装:闭包允许你将数据(变量)封装在函数内部,这样这些数据就只能通过特定的函数来访问和修改,从而保护数据不被外部直接访问。
  3. 访问外部变量:闭包可以访问创建时外部函数作用域中的变量,即使外部函数已经执行完毕。
  4. 持久性:闭包可以保持对创建时环境的引用,这意味着它可以“记住”外部作用域的状态。
  5. 私有变量:通过闭包,你可以创建私有变量,这些变量在闭包外部是不可见的,只能在闭包内部访问。
  6. 延迟计算:闭包可以延迟某些计算,只在必要时才执行,这有助于优化性能。
  7. 状态维护:闭包可以在多次调用之间保持状态,这对于需要维护状态的应用程序非常有用。
  8. 函数定制:闭包可以用来创建定制化的函数,这些函数可以根据传入的参数进行定制化操作。
  9. 高阶函数:闭包的存在使得高阶函数成为可能,这些函数可以接受其他函数作为参数或返回函数。
  10. 记忆化:闭包可以用于记忆化技术,存储昂贵函数调用的结果,避免重复计算。
  11. 模块化:闭包是实现模块化的关键技术之一,它允许将代码组织成独立的模块,每个模块都有自己的私有状态和公共接口。
  12. 函数工厂:闭包可以用于创建函数工厂,这些工厂可以根据传入的参数生成具有特定行为的函数。
  13. 柯里化:闭包支持柯里化,即将一个多参数函数转换成一系列单参数函数,这有助于简化函数调用和参数传递。
  14. 异步编程:在JavaScript的异步编程中,闭包常用于回调函数,它们可以保持异步操作的状态,即使在异步操作完成时外部环境可能已经改变。
  15. 事件处理:在事件驱动的编程中,闭包可以用来访问事件绑定时的状态,即使在事件发生时,绑定时的环境可能已经不存在。

3.闭包如何实现

闭包的实现在JavaScript中是自动的,不需要程序员显式地编写代码来创建。它是由JavaScript的词法作用域和函数作用域的特性自然形成的。以下是闭包实现的基本步骤和原理:

  1. 定义一个函数:首先,你需要定义一个函数。这个函数可以是任何类型的函数,但它必须能够访问到外部作用域中的变量。
  2. 在函数内部创建另一个函数:在这个外部函数内部,定义一个新的函数。这个内部函数将能够访问外部函数的变量。
  3. 外部函数返回内部函数:当外部函数执行时,它返回内部函数。由于JavaScript的词法作用域规则,内部函数会捕获并保留对外部函数作用域的引用。
  4. 外部函数执行完毕:即使外部函数执行完毕并退出了作用域,由于内部函数仍然存在(比如被赋值给了某个变量),它仍然可以访问外部函数的变量。
  5. 使用内部函数:当你在外部函数之外调用内部函数时,你实际上是在使用一个闭包。这个闭包可以访问并操作外部函数作用域中的变量。

下面是一个简单的示例,展示了闭包的实现:

image.png

在这个例子中,createClosure 函数创建了一个内部函数,并将其返回。这个内部函数可以访问 createClosure 函数作用域中的变量 secret。即使 createClosure 函数执行完毕后,myClosure(内部函数的别名)仍然可以访问 secret,因为它形成了一个闭包。

闭包的实现是JavaScript语言的自然结果,它允许程序员编写更加模块化、灵活和功能丰富的代码。然而,使用闭包时也要注意潜在的内存泄漏问题,确保在不再需要闭包时释放其引用的外部变量。

总结

闭包是JavaScript中的一种特性,允许函数访问和操作其外部函数的变量。简而言之:

  • 定义:闭包是记住并访问外部变量的函数。
  • 功能:它们用于数据封装、状态保持和创建私有变量。
  • 实现:通过内部函数访问外部函数的变量自动形成。
  • 注意:使用时要注意避免内存泄漏。