美文网首页
JS 内存回收

JS 内存回收

作者: Tiny_z | 来源:发表于2019-05-14 11:27 被阅读0次

    引用

    垃圾回收算法主要依赖引用的概念,例如一个对象如果有另外一个对象的访问权限,这里就叫做一个对象引用另外一个对象,不论这里是显式还是隐式

    引用计数垃圾收集

    这个算最简单的回收算法,大致是某地对象当没有引用指向它的时候,也就是零指向,这个对象就会被垃圾回收机制回收

    let arr = [1,2,3]
    arr = null  // [1,2,3]没有被引用,会被自动回收
    

    循环引用,低版本浏览器

    下面的例子中,两个对象相互引用,即使函数被调用完成,这里也不会被回收

    function f() {
      var o1 = {};
      var o2 = {};
      o1.p = o2; // o1 引用 o2
      o2.p = o1; // o2 引用 o1. 这里会形成一个循环引用
    }
    f();
    

    标记-清除算法

    这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”
    这个算法假定一个全局对象,然后定期的垃圾回收机制从全局开始,找所有从全局开始引用的对象,然后找这些对象引用的对象。这样就能找到所有可以获得的对象和不能获得的对象。
    现代浏览器都使用了这个回收机制

    img

    自动GC的问题

    自动化的GC很方便,但我们不知道它会什么时候执行,并且如果在使用程序的过程中,我们使用的大量的内存,然后GC没有运行,这时,程序就会假死或者卡顿,然后我们就需要手动做一些操作来触发内存回收

    内存泄漏

    本质上来说,内存泄漏就是不被需要的内存,因为某种原因,没有被回收或者释放

    常见的内存泄漏

    1.全局变量

    function foo(arg) {
        bar = "some text";  // 挂在到window上
        this.arr = [1,2,3];  // this指向window
    }
    

    js中的全局变量,只有当页面被关闭后才会销毁

    2.未销毁的定时器或回调函数

    var serverData = loadData();
    setInterval(function() {
        var renderer = document.getElementById('renderer');
        if(renderer) {
            renderer.innerHTML = JSON.stringify(serverData);
        }
    }, 5000);
    

    上面的代码中,如果后续renderer元素被移除了,然后我们没有清除定时器,这时定时器里面的函数和定时器本身都不会被回收

    3.闭包

    function do(){
        let thing = 'eat'
        return function(){
            console.log(thing)
        }
    }
    
    

    4.DOM引用

    有些时候,当我们要对DOM元素进行操作的时候,会把DOM的引用放在一个数组或对象中

    var elements = {
        image: document.getElementById('image')
    };
    function doStuff() {
        elements.image.src = 'http://example.com/image_name.png';
    }
    function removeImage() {
        document.body.removeChild(document.getElementById('image'));
        // 这个时候我们对于 #image 仍然有一个引用, Image 元素, 仍然无法被内存回收.
    }
    

    建议

    谨慎使用DOM操作,主动删除没有业务意义的变量,合理使用性能监控工具,分析内存的使用状况

    相关文章

      网友评论

          本文标题:JS 内存回收

          本文链接:https://www.haomeiwen.com/subject/qqtsaqtx.html