视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JS内存管理实例讲解
2020-11-27 20:03:28 责编:小采
文档


赋值和New操作都会涉及到内存的占用。

2.2 内存的分配

Chrome V8的垃圾回收(GC)算法基于Generational Collection,内存被划分为两种,分别称为Young Generation(YG)和Old Generation(OG)。

所谓Young和Old是根据他们占用的时间来划分的。内存在YG的分配和回收快而频繁,一般存在的时间很短,所以称为Young;而在OG中则慢而少发生,所以称为Old。

因为在V8中,YG的GC过程会阻塞程序,而OG的GC不会阻塞。所以通常情况下开发者更关心YG的细节。

YG又被平分为两部分空间,分别称为From和To。所有内存从To空间被分配出去,当To满时,开始触发GC,接下来细看一下。

某时刻,To已经分A、B和C分配了内存,当前它剩下一小块内存未分配出去,而From所有的内存都空闲着。

此时,一个程序需要为D分配内存,但D需要的内存大小超出了To未分配的内存,如下图。此时,触发GC,页面停止执行。

接着From和To进行对换,即原来的To空间被标志为From,From被标志为To。并且把活的变量值(例如B)标志出来,而”垃圾“(例如AC)未被标志,它们将会被清掉。

活的B会被复制到To空间,而「垃圾」AC则被回收,同时,D被分配到To空间,最后成下图的分布

至此,整个GC完成,此过程中页面停止执行,所以要尽可能的快。当YG中的值存活比较久时,它会被推向OG,OG的空间满时,触发OG内的GC,OG的GC时会触发YG的GC。

  • 每次分配都使To的可用空间减小,程序又更接近GC

  • YG的GC会阻塞程序,所以GC时间不宜太长10ms以内,因为16ms就会出现丢帧;GC不宜太频繁

  • 某个值变成垃圾后,不会立马释放内存,只有在GC的时候所占内存才会被回收。

  • 2.2 内容均来自参考文献

    2.3 内存的回收

    GC Root是内存的根结节,在浏览器中它是window,在NodeJS中则是global对象。

    从GC Root开始遍历图,所有能到达的节点称为活节点,如果存在GC Root不能到达的节点,那么该节点称为“垃圾”,将会被回收,如图中灰色的节点。

    至于根节点的回收,不受用户的控制。

    3. 导致内存泄漏的原因

    3.1 没有完全切断与GC root之间的路径

    因为没有完全切断与根节点之间的路径,导致自动GC不会回收这部分内存,从而造成内存泄漏。

    具体的原因有:

  • 对象之间的相互引用

  • var a, b;
    a.reference = b;
    b.reference = a;
  • 错误使用了全局变量

  • a = "1234567";
    相当于
    window.a = "1234567";
  • DOM元素清空或删除时,绑定的事件未清除

  • <p id="myp">
    <input type="button" value="Click me" id="myBtn">
    </p>

    <script type="text/javascript">
    var btn = document.getElementById('myBtn');
    btn.onclick = function () {
    document.getElementById('myp').innerHTML = 'Processing...';
    /* 清除事件绑定 */
    // btn.onclick = null;
    };
    </script>

  • 闭包引用

  • function bindEvent() {
    var obj = document.getElementById('xxx');

    obj.onclick = function () {
    /** 空函数*/
    };

    /** delete this reference */
    // obj = null;
    }

  • DOM元素清空或删除时,子元素存在JS引用,导致子元素的所有父元素都不会被删除

  • // b是a的子dom节点, a是body的子节点
    var aElement = document.getElementById("a");
    var bElement = document.getElementById("b");
    document.body.removeChild(aElement);
    // aElement = null;
    // bElement = null;

    3.2 过度占用了内存空间

    更多的出现在nodejs中,例如:

  • 无节制的循环

  • while(1) {
    // do sth
    }
  • 过大的数组

  • var arr = [];
    for (var i=0; i< 100000000000; i++) {
    var a = {
    'desc': 'an object'
    }
    arr.push(a);
    }

    相关推荐:

    详细介绍Linux中的内存管理

    php内存管理之垃圾回收机制的详解(图)

    如何避免JavaScript的内存泄露及内存管理技巧

    下载本文
    显示全文
    专题