一.闭包的内存泄漏
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引擎基于优化这个角度,会将这个用不到的属性删除掉的。