闭包中的内存泄漏

文章讨论了闭包在JavaScript中的内存管理问题,特别是闭包如何导致内存泄漏以及如何解决。当闭包引用外部函数的活动对象(AO对象)时,即使外部函数执行完毕,AO对象也不会被销毁。这可能导致内存泄漏,特别是在只执行一次闭包函数时。解决方法是断开引用,如设置`fn=null`。此外,文章提到JS引擎可能会优化未使用的属性,如V8引擎可能会删除不再使用的AO对象属性以释放内存。
摘要由CSDN通过智能技术生成

一.闭包的内存泄漏

1.为什么有些AO对象就不会被销毁?
1)普通函数中

在这里插入图片描述
上述代码在执行foo函数的时候,内存中的过程。
在这里插入图片描述
执行完foo函数之后,foo的函数上下文被销毁了,那么就不会指向foo的AO对象了。
在这里插入图片描述
那么AO对象也会被销毁,但为什么在闭包中的有些这样的AO对象就不会被销毁呢?

2)在闭包中

因为闭包中能够在函数中返回函数,就比如return bar,所以就等于说有变量指向了这个函数对象,那么这个函数对象有了指向就不会被销毁,那么这个函数指向的对象也就不会被销毁。
因为没有对象指向它了,所以会被销毁,而在闭包中,即便函数上下文被销毁了,但是还有对象指向AO对象。

在这里插入图片描述
上述函数中,执行到第12行代码的时候,过程如下:
在这里插入图片描述
在执行到foo函数的最后的时候,return bar,其实就是return 0xb00,也就是将fn赋值为了0xb00,那么这个时候,bar对象就不会被销毁,bar对象不会被销毁,且bar对象还指向了foo函数的AO对象,也就是指向了上层作用域,那么这个AO对象也就不会被销毁。
但是如果没有了指向依旧会被销毁,执行最后一行代码的时候,实际上就是执行了bar函数,但是bar函数中就只有一个打印操作,只有bar函数的执行上下文指向bar函数的AO对象,当函数执行完毕之后,就没有东西指向bar函数的AO对象了,那么它的AO对象照样会被销毁。

2.闭包中的内存泄漏

如果在下面这段代码中,执行多次fn(),那么其实bar函数对象就一直没有被销毁,那么也就意味着它所指向的foo函数的AO对象也就一直没有被销毁,这样是没有问题的。
在这里插入图片描述
但是如果就只执行了一次fn(),那么原本就应该被销毁的foo函数的AO对象一直没有被销毁,一直占用内存,这个时候就出现了内存泄漏,就是说原本再也不会使用的东西,原本应该被销毁的,但是垃圾回收没有办法回收,因为仍然有指针指着它,这就是内存泄漏。
解决上述内存泄漏,其实只需要将fn=null ,就是fn 不指向了,那么这个AO的内存就会被释放,它和bar函数是互相指向的,但是按照GC最新的规则是会被回收的,它们就被销毁了。

二.闭包中AO对象不再使用的属性

这里有一段代码:
在这里插入图片描述
上述代码中调用了一次foo()函数,创建了一个AO对象和一个foo函数对象,如果在下面多次调用这个foo()函数且用一个变量来接收引用它,那么在内存中会创建多个foo函数对象和AO对象,它们是互不干扰的,如果把fn=null,是不会销毁其他的AO对象和foo函数对象的。
下面将到一个问题,就是在foo的AO对象中会定义两个属性,name和age,但是在实际使用的时候发现,只使用了name这个变量,age属性一直没有被使用。
在这里插入图片描述
虽然按照闭包的概念来讲,foo的AO对象不会被销毁,也就是说AO对象中的所有属性都不会被销毁,但是对于JS引擎的实现来说是十分灵活的,例如是V8引擎,为了提供性能,释放更多的空间,当发现上面的age属性永远不会使用的时候,是有必要将这个用不到的属性删除掉的,JS引擎基于优化这个角度,会将这个用不到的属性删除掉的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值