闭包如何导致内存泄漏以及如何防止?
闭包
Javascript 的优势之一是闭包。Javascript 允许嵌套函数(一个函数在另一个函数内部)访问父函数的变量。这个由内部函数访问外部函数变量的过程称为闭包。当声明的变量自动可用于内部嵌套函数并在内存中驻留,即使它在内部嵌套函数中没有被引用时,就会发生内存泄漏。
在下面的例子中,'childFunction' 是在外部函数 'parentFunction' 内定义的内部函数。当用参数 "outer val" 调用 'parentFunction' 时,外部变量 a 将被赋值为 "outer val"。该函数返回一个指向内部函数 "childFunction" 的指针,该指针包含在变量 'val' 中。
即使外部函数已返回,外部函数的局部变量 a 仍然存在。在 Javascript 中,一旦调用 parentFunction,就会创建一个具有属性 'a' 的作用域对象。此属性包含 arg1 的值,也称为 "outer val"。类似地,当 parentFunction 返回时,它将返回内部函数 (childFunction),该函数包含在变量 val 中。
由于内部函数持有对外部函数变量的引用,因此具有属性 'a' 的作用域对象将不会被垃圾回收。
示例
<html> <body> <script> window.onload= function parentFunction(arg1) { var a = arg1; return function childFunction (arg2) { alert( a +" "+ arg2); }; }; var val = parentFunction("outer val"); val("inner val"); </script> </body> </html>
避免内存泄漏
添加另一个函数
通过添加另一个函数,将有两个内部函数。由于有两个内部函数,因此没有函数可以引用外部函数的变量,从而完全停止闭包。
当没有闭包时,内存泄漏的可能性就会减少。
示例
<html> <body> <script> window.onload=function parentFunction(){ var Obj1 = function childFunction1() { document.write("the leak is avoided"); }; (function childFunction2(){ var obj2 = document.getElementById("closure"); obj2.onclick=Obj1 })(); }; </script> <input type = "button" id="closure" value ="Click Here"> </body> </html>
代码执行后,将显示如下按钮
按下按钮后,我们将得到如下输出
输出
the leak is avoided
广告