详细解释 JavaScript 中的内存泄漏?


JavaScript 内存泄漏

JavaScript 是一种垃圾收集语言,这意味着当声明变量时,它会自动为它们分配内存。当没有更多对已声明变量的引用时,分配的内存将被释放。内存泄漏或大多数与内存相关的問題都发生在释放内存期间。

一些常见的 JavaScript 内存泄漏

1) 意外的全局变量

当引用未声明的变量时,javascript 会在全局对象中创建一个新变量。在下面的示例 1 中,假设语言的目的是仅引用 "myArray" 函数中的变量。如果我们不使用 var 声明它,则会创建一个全局变量。它可能不会造成太大危害,但主要问题在于意外地使用 "this" 关键字创建全局变量,如示例 2 所示。

示例 1

function myArray(arg) {
   languages = "[javascript,.....]";  //  created using window
}

示例 2

function myArray(arg) {
   this.languages = "[javascript,.....]";  // global object  
}

由于全局变量的作用域永不结束,因此即使不需要它们,它们也会在页面执行期间一直保留在内存中。这种情况会导致垃圾收集器(在变量作用域结束时删除动态内存)产生内存泄漏(内存中残留未使用的对象)。全局变量越多,内存泄漏就越多。

2) 闭包

闭包是一个内部函数,可以访问外部函数的变量(作用域)。此外,即使外部函数已执行,内部函数仍将继续访问外部函数的作用域。当声明的变量自动可用于内部嵌套函数并在内存中驻留,即使它在内部嵌套函数中没有被引用时,也会发生内存泄漏。

在下面的示例中,由于闭包中的所有内部函数共享相同的上下文,innFun() 与 "function() {}" 共享相同的上下文,该上下文由外部函数返回。现在,每隔 3 毫秒,我们对 outFun 进行一次函数调用,一个新值(每次调用后)被分配给全局变量 newvalue。只要一个引用指向此 "function() {}",就会保持共享作用域并保留数组,因为它是内部函数 (innFun) 的一部分,即使内部函数从未被调用。每次调用外部函数 (outFun) 时,我们都会将前一个 function(){} 保存到新函数的值(变量)中。因此,以前共享的作用域必须再次保留。因此,在外部函数 (outFun) 的第 n 次调用中,外部函数的第 (n-1) 次调用的数组无法被垃圾回收。此过程最终会在内存耗尽时停止。

示例

var newvalue;
function outFun() {
   var array = new Array(1000000);
   var value = newvalue;
      function innFun() {
        if (value) return array;
   }
   return function () {};
}
setInterval(function () {
   newvalue = outFun();
   }, 3);

更新于:2020年7月4日

488 次浏览

启动你的职业生涯

完成课程获得认证

开始学习
广告