美文网首页
JS垃圾回收机制和内存泄漏

JS垃圾回收机制和内存泄漏

作者: vinterx | 来源:发表于2019-05-06 00:12 被阅读0次

一、浏览器内存泄漏

浏览器封装的V8引擎支持对JS进行解析,当程序运行(runtime)时,只要程序提出需要内存,例如声明赋值字符串、对象、数组等变量时;操作系统就必须给分配内存使用,对于持续运行的服务进程,变量不断增加,并且内存没有得到及时的释放,内存占有会越来越大,轻则影响系统性能,重则直接导致系统崩溃。

1、闭包加引用

    let fn = () =>{
        let a = 0
        return () => {
            return a++
        }
    }

    let b = fn()
    console.log(b())    // 0
    console.log(b())    // 1

闭包在IE6下会造成内存泄漏,但是现在已经无须考虑了。虽然变量a无法被回收(相当于全局变量),但是这点内存无须特别考虑,值得注意的是闭包本身不会造成内存泄漏,但闭包过多很容易导致内存泄漏。
2、相互引用

let aa = {}
let bb = {}
aa.c = bb
bb.c = aa

解决办法:不要互相引用变量
4、全局未声明的变量

    function fn1() {
        aa = 1  //  window.aa
        console.log(aa)
    }
    fn2()

    function fn2() {
        this.bb = 1 //  window.bb
        console.log(bb)
    }
    fn2()

函数fn1和fn2均未声明,即将变量绑定到了全局对象window下,这样函数执行完毕均不能释放变量内存。

解决办法:使用严格模式,在js顶部加上‘use strict’

5、定时器和回调函数

    let a = 2
    setInterval(() =>{
        console.log(a++)
    }, 1000)

当不需要setInterval或者setTimeout时,定时器没有被clear,定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄漏。

6、DOM对象添加属性

document.getElementById('id')[property] = obj

DOM如果存在会一直绑定这个事件,解决办法如下:

window.onunload = function(){
  document.getElementById('id')[property] = null
}

7、vue中的定时器,事件监听,$on等
解决办法:在beforeDestroy钩子中移除或关闭相关事件

借鉴链接内存泄漏

二、垃圾回收机制

变量的生命周期:当一个变量的生命周期结束之后它所指向的内存就应该被释放。JS有两种变量,全局变量和在函数中产生的局部变量(不包括被引用的变量)。局部变量的生命周期在函数执行过后就结束了,此时便可将它引用的内存释放(即垃圾回收),但全局变量生命周期会持续到浏览器关闭页面。垃圾收集器会检测不再继续使用的变量,然后释放其占用的内存,并按照固定的时间间隔周期性的执行。

现代浏览器垃圾回收机制主要有两种:标记清除和引用计数。
1、标记清除(mark-and-sweep)
目前主流IE,Firefox,Opera,Chrome和Safari等浏览器均使用标记清除的垃圾收集策略。
工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

工作流程:
1.垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
2.去掉全局中的变量以及被环境中的变量引用的变量的标记。
3.被加上标记的会被视为准备删除的变量。
4.垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

2、引用计数(reference counting)
引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1,如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值的引用的变量又取得了另外一个值,则这个值的引用次数减1,当这个值的引用次数为0时,则说明没有办法再访问这个值了,因此就可以将其占用的内存空间回收回来。

let aa = []   // 数组[]引用1次
let bb = aa  //  数组引用2次
bb = null  //  释放内存,引用还剩下1次,即变量aa的引用还存在

这样简单的垃圾回收机制,非常容易出现循环引用问题导致内存不能被回收, 进行导致内存泄露等问题; 如:

let aa = {}
let bb = {}
aa.c = bb
bb.c = aa
var wraper = document.querySelector('#btn');
wraper.onclick = handle;
wraper = null;

该方法并不能解除dom点击事件,因为释放的是wraper引用的这个变量,实际对象DOM已经绑定了这个btn点击事件,举个例子

    let a = {}
    let b = a
    b.btn = () =>{}
    b = null
    console.log(a)
对象引用.png

相关文章

  • 前端面试-JS垃圾回收机制

    什么是垃圾回收机制? JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在...

  • 垃圾回收机制

    概述 JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制...

  • JS 里垃圾回收机制是什么,常用的是哪种,怎么处理的?

    JS 的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制就是...

  • JS的内存泄漏垃圾回收

    一.垃圾回收 JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃...

  • 对 Java 内存的一些理解-[Android_YangKe]

    Java 垃圾回收机制优点 Java 内存模型 什么是内存抖动 什么是内存泄漏 垃圾回收机制常见算法 Java 垃...

  • Android 优化

    Android 内存优化内存溢出 , 内存泄漏 , 内存泄漏过多就导致内存溢出 Android 系统垃圾回收机制内...

  • 2018-03-16

    什么是内存泄漏 内存泄漏是指一块被分配的内存既不能被使用又不能被回收,直到浏览器的进程结束。 JS中的垃圾回收机制...

  • 2018-10-13

    浅谈浏览器的垃圾回收机制和内存泄露 JavaScript使用垃圾回收机制来自动管理内存。 JS的回收机制分两种:1...

  • 2017.11.09正则表达式

    垃圾回收 垃圾回收机制:内存泄漏 垃圾回收/生命周期 正则表达式(规则表达式) Regular Expressio...

  • Android性能优化之内存泄漏

    内存泄漏:内存单元使用完成后未释放,未回收。理解强弱引用和gc垃圾回收机制后,会更好的理解内存泄漏问题。 在目前的...

网友评论

      本文标题:JS垃圾回收机制和内存泄漏

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