内存管理与垃圾回收

58 阅读2分钟

内存管理都是针对内存生命周期的管理。

内存的生命周期无外乎分配内存读写内存释放内存

var str = 'string'; // 分配内存
console.log(str); // 读写内存
str = null; // 释放内存

内存空间可分为栈空间和堆空间。

  • 栈空间:由操作系统自动分配释放,存放函数的参数值,局部变量的值等。操作方式类似数据结构中的栈

一般情况下,基本数据类型按照大小保存在栈空间中,占有固定大小的内存空间

  • 堆空间:一般由开发者分配释放,需要考虑垃圾回收的问题。

引用类型保存在堆空间中,内存空间大小并不固定,需按引用情况来进行访问。

内存泄漏

内存泄漏是指内存空间命名已经不再被使用,但由于某种原因并没有被释放的现象。内存泄漏会导致程序运行缓慢,甚至崩溃。

  • 例子1:
var elem = document.querySelector('#id');
elem.mark = 'marked';

// 移除节点
function remove() {
    elem.parentNode.removeChild(elem);
}

remove();

上述操作只是把节点移除了,但是变量elem依然存在,该节点的内存无法被释放。为解决问题需要在remove方法中添加elem = null;

  • 例子2:
// 事件处理句柄
elem.innerHTML = '<button id="btn">点击</button>';
var btn = document.querySelector('#btn');
btn.addEventListener('click', function() {
    // ...
});
elem.innerHTML = '';

elem.innerHTML = ''移除了button,但事件处理句柄还在,因此该节点变量依然无法回收。因此还需添加removeEventListener函数

  • 例子3:
function fn () {
    var name = 'hd';
    window.setInterval(() => {
        console.log(name);
    }, 1000);
}
fn();

由于存在setInterval,所以name内存空间无法释放,如果不是业务要求,要在合适的时机使用clearInterval清理

  • 内存泄漏与垃圾回收注意事项
function fn () {
    var value = 123;
    function bar () {
        console.log(bar);
    }
    return bar;
}

let bar = fn();

变量value将会被保存到内存中,如果运行结束后加上bar = null,则随着bar不再被引用,value也会被清除

function fn () {
    var value = Math.random();
    function bar () {
        debugger;
    }
    return bar;
}

let bar = fn();
bar(); // 实际value并未被引用