• 内存泄漏、垃圾回收机制、哪些情况会导致内存泄漏


    http://www.ruanyifeng.com/blog/2017/04/memory-leak.html

    什么是内存泄漏?
    内存泄漏是指不再用到的内存,没有及时释放。既不能使用,又不能回收。

    程序的运行需要内存。对于持续运行的进程,如果不及时释放不再用到的内存,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。

    要了解 JS 内存泄漏的几种情况,我们首先来了解一下 JS 的内存是如何管理的,即 JS 的垃圾收集机制。

    垃圾收集机制
    Javascript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中的使用的内存。所需内存的分配 以及无用的回收 完全实现了自动管理。

    JavaScript 垃圾回收机制很简单:找出不再使用的变量,然后释放掉其占用的内存。但是这个过程不是时时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。

    JavaScript 中最常用的垃圾收集方式有 2 种:标记清除和引用计数。

    1)“标记清除”——当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。当变量离开环境时,这将其 标记为“离开环境”。

    从逻辑上讲,永远不能释放进入环境的变量所占的内存,因为只要执行流进入相应的环境,就可能用到它们。

    function fun(){
    var a = 1;//被标记 进入环境
    var b= 2;//被标记 进入环境
    }
    fun();//执行完毕之后,a,b 被标记离开环境,被回收

    如果我们的代码写法不当,会让变量一直处于“进入环境”的状态,无法被回收。

    2)“引用计数”——语言引擎有一张”引用表”,跟踪记录每个值被引用的次数。
    如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。

    如果一个值不再需要了,引用数却不为0,垃圾回收机制无法释放这块内存,从而导致内存泄漏。

    那些很占空间的值,一旦不再用到,你必须检查是否还存在对它们的引用。如果是的话,就必须手动解除引用。

    function test(){
    var a = {} ; //a的引用次数为0
    var b = a ; //a的引用次数加1,为1
    var c = a; //a的引用次数再加1,为2
    var b ={}; //a的引用次数减1,为1
    }

    导致内存泄漏的几种情况
    1. 意外的全局变量
    function leaks(){
    leak = 'xxxxxx';//leak 成为一个全局变量,不会被回收
    }

    调用完函数以后,变量仍然存在,导致泄漏.
    你可以通过加上 ‘use strict’ 启用严格模式来避免这类问题, 严格模式会阻止你创建意外的全局变量.

    2. 闭包
    闭包可以维持函数内局部变量,使其得不到释放。
    解决办法:在函数外部定义事件处理函数,解除闭包。或在闭包中,删除没用的属性以减少对内存的消耗。或在外部函数中删除对DOM的引用

    function bindEvent()
    {
    var obj=document.createElement("XXX");
    obj.onclick=function(){
    //Even if it's a empty function
    }
    obj=null;
    }

    3. 未清除 dom 元素的引用
    dom 元素移除,但 对 dom 元素的引用没有解除,会导致内存泄漏。
    解决办法:手工移除。

    var elements = {
    button: document.getElementById('button'),
    image: document.getElementById('image')
    }

    function doStuff() {
    image.src = 'http://some.url/image';
    button.click();
    console.log(text.innerHTML);
    }

    function removeButton() {
    document.body.removeChild(document.getElementById('button'));
    // 虽然我们用removeChild移除了button, 但是还在elements对象里保存着#button的引用
    // 换言之, DOM元素还在内存里面.
    }

    4.循环引用
    循环引用 在引用计数策略下会导致内存泄漏,标记清除不会。
    解决办法:手工解除循环引用。

    function fn() {
    var a = {};
    var b = {};
    a.pro = b;
    b.pro = a;
    }
    fn();

    a和b的引用次数都是2,fn()执行完毕后,两个对象都已经离开环境。
    在标记清除方式下是没有问题的,但是在引用计数策略下,a和b的引用次数不为0,不会被垃圾回收器回收内存。如果fn函数被大量调用,就会造成内存泄漏。

    IE中的BOM和DOM中的对象使用C++以COM(component Object Model,组件对象模型)对象的形式实现而COM对象的垃圾收集机制采用的是引用计数策略。换句话说,只要在IE中涉及COM对象,就会存在循环引用的问题。

    var element = document.getElementById("some_element");
    var myObject = new Object();
    myObject.e = element;
    element.o = myObject;
    //手工断开它们之间的连接
    myObject.element=null;
    element.someObject=null;

    5. 被遗忘的计时器或回调
    var someResource = getData();
    setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
    node.innerHTML = JSON.stringify(someResource));
    }
    }, 1000);

    原文:https://blog.csdn.net/meijory/article/details/76839072
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    由Highcharts加载提示想到的:我想要的别人已经做好了
    ajaxmin js压缩和VS(转1)
    ajaxmin js压缩和VS(转2)
    Silverlight客户端怎样获取外部参数
    SQL中的事务
    qt webkit 中文乱码问题 另辟蹊径
    密码学基础(1)
    使用jQuery的属性[attr]筛选
    Leetcode NO.19 Remove Nth Node From End Of List && 移除链表倒数第n个节点
    经典排序算法(一) —— Selection Sort 选择排序
  • 原文地址:https://www.cnblogs.com/leftJS/p/10947350.html
Copyright © 2020-2023  润新知