闭包如何导致内存泄漏以及如何防止?


闭包

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

更新于:2019年7月30日

2K+ 次浏览

启动您的职业生涯

通过完成课程获得认证

开始
广告