详细解释 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);