JS 的内存泄漏问题

298 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情

内存泄漏,是指当内存不再被应用程序使用的时候,由于某种原因,这块内存没有被释放现象

在编程语言中,基本都会涉及到内存泄漏的问题。在程序中编写指令,定义变量等,系统就会分配内存,当我们不再使用这个数据,或者关闭程序时,就需要释放内存。当内存没有及时释放,就会产生内存泄漏。

情况一:

在 JS 中,未进行声明的变量在引用时,会在全局对象内创建一个新变量。(全局对象就是浏览器中的 window)。

function say() {
    msg = 'hello'; 
}

注:上述代码中的语句,等同于 window.msg = 'hello';

关闭页面前,全局变量会持续存留在内存中,

解决方案:

在 JS 文件开头添加 use strict 严格模式。这样可以防止意外的全局变量,在使用完之后,可以再将其赋值为 null

情况二:

除此之外,setTimeout 和 setInterval 也是可能或造成内存泄漏的原因

var serverData = loadData();

setInterval(function() {

var renderer = document.getElementById('renderer');

if(renderer) {

renderer.innerHTML = JSON.stringify(serverData);

}

}, 5000);

情况三:

JS 中闭包表示一个可以访问外部函数变量的内部函数。以下代码形成闭包可能出现泄漏内存的问题,函数执行完毕,但是内存没有被回收。下面这段代码创建了闭包,即使有些代码声明了但是没有使用,依旧可以在外部被访问

var a = null;
var func1 = function () {
    var b = a;
    var func1 = function () {
        if (b) 
            console.log("111");
        };
        a = {
            myArr: new Array(100).join('*'),
            myFunc: function() {
                console.log("222");
            }
        }
    }
}
setInterval(func1, 1000);

情况四:DOM 引用

如果每行 DOM 的引用存储在字典或数组中,就会保留一个 DOM 元素的两份引用:一个引用在 DOM 中,另一个引用在字典中。只有在DOM和另外的引用上同时移除了,才可以被 JS 的回收机制回收

let obj = {
    image: document.getElementById('image'),
};

function setData() {
    obj.image.src = './imag1.png';
}

function remove() {
    document.body.removeChild(document.getElementById('image'));
}

所以综合上面的几种情况,解决内存泄漏也要从:全局变量、setTimeout 和 setInterval 、闭包、DOM 引用这几点入手来避免或者解决。