js中的内存泄漏

概述

以前虽然知道函数做用域, 上下文, 做用域链, 闭包, 引用清除与标记清除等概念, 可是总以为既然有标记清除, js就不怎么会发生内存泄漏. 今天查了下资料, 梳理了一下, 记录下来供之后开发时参考, 相信对其余人也有用.node

全局变量

function foo(arg) {
bar = "this is a hidden global variable";
}

如上代码, 声明了一个全局变量, 它不会被自动回收, 因此会形成内存泄漏. 须要手动回收, 改为以下所示:chrome

方法一(推荐)
function foo(arg) {
var bar = "this is a hidden global variable";
}

方法二
function foo(arg) {
bar = "this is a hidden global variable";
// Do something;
bar = null;
}

计时器

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
    // Do stuff with node and someResource.
    node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);

上面的计时器不断的执行函数, 在执行的时候会调用外面的变量someResource, 因此someResource一直在内存中没法被释放. 要修正这种内存泄漏只能设置一个计时器的中止条件了.缓存

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
    // Do stuff with node and someResource.
    node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);
if(timesRun === 60){
clearInterval(interval);
}

dom相关操做

<div id="container">  
</div>

$('#container').bind('click', function(){
    console.log('click');
}).remove();

上面删除了dom可是没有删除绑定的事件, 也会形成内存泄漏. 解决方法是先把事件清除再remove.闭包

<div id="container">  
</div>

$('#container').bind('click', function(){
    console.log('click');
}).off('click').remove();

闭包

var leaks = (function(){
    var leak = 'xxxxxx';// 被闭包所引用,不会被回收
    return function(){
        console.log(leak);
    }
})()
leaks();

上面的leak被闭包所引用, 因此不会被回收.解决方法是在执行操做以后释放掉内存.dom

var leaks = (function(){
    var leak = 'xxxxxx';// 被闭包所引用,不会被回收
    return function(){
        console.log(leak);
        leak = null;
    }
})()
leaks();

不被注意的内存泄漏

有一种内存泄漏很常见, 可是不是那么明显, 代码以下:函数

window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=function innerFunction(){};
};

这是一个很常见也用的较多的事件绑定代码, 它其实是闭包引发的内存泄漏问题. 首先咱们在内层函数中声明了一个变量obj, 而后咱们给obj绑定了一个click事件, 这个click事件被外层window引用, 致使innerFunction()函数造成了一个闭包, 虽然这个函数里面没有任何表达式, 可是其中的this指向了obj, 因此obj在代码执行结束以后并不会被清除, 须要手动释放.修改方法以下:工具

方法一(推荐):
window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=function innerFunction(){};
    obj = null;
};

方法二(不推荐):
function innerFunction(){};
window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=innerFunction;
    obj = null;
};

值得注意的是, jQuery封装了解决这种内存泄漏的方法, 它的原理是使用jQuery缓存来绑定事件, 因此存下下面的方法三. 可是为了保险起见, 仍是建议使用方法一手动清除声明的变量.this

window.onload=function outerFunction(){
  var obj = document.getElementById("element");
  $(obj).click(function innerFunction(){});
};

查看内存泄漏

使用chrome可以很方便的查看网页的内存使用状况, 操做以下:code

  1. 打开开发者工具,选择 Network 右边的 Timeline 面板
  2. 在顶部的Capture字段里面勾选 Memory
  3. 点击左上角的录制按钮。
  4. 在页面上进行各类操做,模拟用户的使用状况。
  5. 一段时间后,点击对话框的 stop 按钮,面板上就会显示这段时间的内存占用状况。
相关文章
相关标签/搜索