1

引言

内存泄漏一般是由于我们编码缺陷导致的,首先明确一下内存泄漏的定义,就是应用程序不需要,但是又不能返回给操作系统以供重新分配使用,导致可用内存越来越少的现象。下面总结一下在browser端内存泄漏几种方式

全局变量

function test () {
    age ='xxx'
    this.name = 'ycg'
}
test()

说明
本来函数执行完栈释放,但是失误行为,导致栈中本应该声明为局部的变量变成了全局,导致变量所占用空间无法释放,好的编码习惯可以防止此类失误,例如借助eslint等

定时器

 var someResource = 'jsdt'.repeat(100000);
    setInterval(function() {
        var node = document.getElementById('node');
        if(node) {
            // Do stuff with node and someResource.
            node.innerHTML = JSON.stringify(someResource);
        }
    }, 100);

说明 由于定时器中持有node节点引用,导致即使node节点被移除,所占据空间任然无法被释放

闭包

var theThing = null;
var replaceThing = function () {
  var originalThing = theThing;
  // Define a closure that references originalThing but doesn't ever
  // actually get called. But because this closure exists,
  // originalThing will be in the lexical environment for all
  // closures defined in replaceThing, instead of being optimized
  // out of it. If you remove this function, there is no leak.
  var unused = function () {
    if (originalThing)
      console.log("hi");
  };
  theThing = {
    longStr: new Date()+new Array(1000000).join('*'),
    // While originalThing is theoretically accessible by this
    // function, it obviously doesn't use it. But because
    // originalThing is part of the lexical environment, someMethod
    // will hold a reference to originalThing, and so even though we
    // are replacing theThing with something that has no effective
    // way to reference the old value of theThing, the old value
    // will never get cleaned up!
    someMethod: function () {}
  };
  // If you add `originalThing = null` here, there is no leak.
};
setInterval(replaceThing, 1000);

说明 注释中已经很好的说明了产生现象的原因,就是说同一父级作用域创建的各种闭包作用域是共享的,unused引用originalThing,虽没使用,但是词法作用域环境已经创建。假如没有unused,此时v8会进行优化,把不会被任何闭包用到的变量从词法环境中去掉,从而消除内存泄漏。下图是我本地browser实验现象截取,可以看到使用内存一直在增加,并且从对比视图中看到,一直有新的string被创建,只增不减。
mem-leak-gcy
mem-leak-compare-gcy

游离DOM引用

dom-gc

图示dom树中,如果#tree变成游离态,但是叶子节点leaf被js变量引用。除非消除引用,否则游离态的#tree无法被GC

总结

首先必须明确的概念是浏览器不能帮助我们解决内存泄漏,只是帮我们GC,免得人力手动GC。GC算法规则限制了只能清除符合特定条件的对象。良好的编码方式,了解一下常见memory leak现象可以减少内存泄漏现象产生,同时在由于失误产生泄漏时,保持清醒的思路,借助devtool进行分析定位。

参考链接

https://blog.meteor.com/an-in...
https://blog.sessionstack.com...


jsdt
4.9k 声望3.9k 粉丝

make a little progress every day


« 上一篇
性能优化
下一篇 »
非常规优化