JS的垃圾回收机制

  1. 概述
    JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。
    C#、Java、JavaScript有自动垃圾回收机制,但c++和c就没有垃圾回收机制,也许是因为垃圾回收机制必须由一种平台来实现。在JS中,JS的执行环境会负责管理代码执行过程中使用的内存
    2.变量的生命周期
    当一个变量的生命周期结束之后它所指向的内存就应该被释放。JS有两种变量,全局变量和在函数中产生的局部变量。局部变量的生命周期在函数执行过后就结束了,此时便可将它引用的内存释放(即垃圾回收),但全局变量生命周期会持续到浏览器关闭页面。
  2. JS垃圾回收方式
    JS执行环境中的垃圾回收器怎样才能检测哪块内存可以被回收有两种方式:标记清除(mark and sweep)、引用计数(reference counting)。
    3.1 标记清除
    这是javascript中最常用的垃圾回收方式。当变量进入执行环境是,就标记这个变量为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。当变量离开环境时,则将其标记为“离开环境”。
    垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后。垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
    3.2 引用计数
    所谓"引用计数"是指语言引擎有一张"引用表",保存了内存里面所有的资源(通常是各种值)的引用次数。如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。
    4 内存泄漏
    4.1 意外的全局变量
    比如 function(){ bar = '小猪' } 这里bar就没有被声明会变成一个全局的变量,再页面关闭之前不会被释放,还有
    function foo(){
    this.name = '小猪'
    }
    foo()
    这种自己调用自己的也会this指向了全局对象 window
    4.2 被遗忘的计时器或回调函数
    计时器或者回调函数中使用了某个上面的变量。但是结束后计时器和回调函数没有被清除,那么他所使用的上面的变量也会一直被引用,从而不被垃圾回收机制所收回。
    4.3 闭包
    闭包可以维持函数内局部变量,使其得不到释放。
    解决方式:将时间处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,清除原本声明的变量。
    4.4 没有清理的DOM元素引用
    如果显示在某个地方,用document获取某个DOM元素,并且赋给某个值,就算是下面你在h5的页面中把那个节点给移除了,但是你的js代码中还是有这个dom,换而言之,DOM元素还存在内存里面。
    5 内存泄漏的识别方法
    步骤:打开开发者工具 Performance
    勾选 Screenshots 和 memory
    左上角小圆点开始录制(record)
    停止录制
    图中 Heap 对应的部分就可以看到内存在周期性的回落也可以看到垃圾回收的周期,如果垃圾回收之后的最低值(我们称为min),min在不断上涨,那么肯定是有较为严重的内存泄漏问题。
    6 避免内存泄漏的一些方法
    减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收。
    注意程序的逻辑,避免死循环之类的
    避免创建过多的对象
    总而言之,不用的东西要及时的归还
    7 垃圾回收的使用场景优化
    7.1 数组array的优化
    arr = [],这种方式虽然把原来的给释放了,但是又创建了一个新的空对象,实际上,将数组的长度赋值为0,arr.length = 0 能够达到清空数组的目的,并实现了数组的重用,减少内存垃圾的产生.
    7.2 在循环的函数表达式,能复用的最好放在外面
    // 在循环中最好也别使用函数表达式。
        for (var k = 0; k < 10; k++) {
          var t = function(a) {
            // 创建了10次  函数对象。
            console.log(a)
          }
          t(k)
        }
        写成
        // 推荐用法
        function t(a) {
          console.log(a)
        }
        for (var k = 0; k < 10; k++) {
          t(k)
        }
        t = null

总结参考:https://juejin.im/post/5cb33660e51d456e811d2687

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容