对闭包的理解

本文详细介绍了闭包的概念,包括其作为保护变量、存储状态、实现函数工厂和模块化的角色。同时也探讨了闭包可能导致的内存泄漏和性能问题,以及如何避免常见的内存泄漏情况,如未释放引用、循环引用和大型对象引用。

一、闭包是什么样的?

如图所示就是一个非常典型的闭包结构,函数嵌套函数。f函数作为外包函数包围着它的内部变量count和内部函数即闭包函数fun,外部的num变量承接了return出来的闭包函数fun。

二、闭包函数发挥了什么作用?

  1. 保护变量,防止变量被污染:闭包可以创建一个私有的作用域,将变量隐藏起来,避免全局污染和命名冲突。通过闭包,内部函数可以访问外部函数中的变量,但是外部函数无法直接访问内部函数中的变量,从而实现了变量的封装和保护。

  2. 存储状态:闭包可以通过持续引用外部作用域中的变量,使得这些变量的状态得以保持。每当调用闭包函数时,它可以访问和操作其创建时所处的上下文中的变量。这使得闭包在处理记忆化、缓存或保存状态等需要长期存储数据的场景中非常有用。

  3. 实现函数工厂和高阶函数:闭包可以用于创建函数工厂,即返回特定类型函数的函数,从而简化代码编写。同时,闭包也为高阶函数提供了基础,允许将函数作为参数传递、返回函数,并且可以捕获上下文环境中的变量。

  4. 实现模块化:通过使用闭包,可以实现模块化的代码结构。将相关的变量和功能封装在闭包中,只暴露必要的接口给外部,从而达到信息隐藏和代码组织的目的。

 三、闭包函数可能带来的问题。

  1. 内存泄漏:当变量被闭包函数持续引用时,即使不再需要这些变量,垃圾回收机制也无法释放对应的内存,导致内存泄漏。
  2. 性能问题:闭包会创建额外的作用域链,并且每次访问闭包中的变量都需要通过作用域链进行查找,这会带来一定的性能损失。
  3. 难以维护的代码:闭包使得代码的逻辑复杂化,增加了对变量生命周期的管理难度,容易造成意外的行为或 bug。

四、内存泄漏的常见情况

1.未正常释放闭包

在上面的例子中,如果我们没有明确解除对闭包的引用,频繁调用closure(),闭包将继续存在并保持对其父级作用域中的变量的引用,从而可能导致内存泄漏。可以显式解除对闭包的引用,例如在return闭包函数的下面把data赋值为null。

这个例子用了定时器进行频繁调用:

2.循环引用(避免使用就对了)

在这个例子中,innerFunction 形成了一个闭包,可以访问 outerFunction 中的变量。然而,由于 innerFunction 中引用了 outerFunction,并且 outerFunction 中又引用了 innerFunction,这导致了循环引用关系。即使对闭包和外部函数的引用被解除,垃圾回收机制也无法回收相关内存。

3.大型对象的引用(这个也避免使用就对了)

new Array(1000000).fill('data')的意思是创建了一个长度为 1000000 的数组,并将每个元素都填充为字符串 'data'。

在上面的例子中,闭包中引用了一个非常大的数组。即使不再需要使用闭包,该闭包仍然保留对这个大型数组的引用,导致该数组无法被垃圾回收机制回收,从而可能导致内存泄漏。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值