JS垃圾回收和内存泄露

1.JS垃圾回收有几种方式
2.什么方式会引发内存泄露
3.如何避免内存泄漏,有几种方式
4.JS的栈内存和堆内存
复制代码

垃圾回收的方式

原理:垃圾收集器会按期(周期性)找出那些不在继续使用的变量,而后释放其内存。程序员

JS具备自动垃圾回收机制,GC(Garbage collection)不是实时的,由于开销比较大,因此回收会按照固定的时间间隔周期性执行。算法

  • 回收方法一:标记清除
    • 当变量进入环境时,标记为“进入环境”,离开环境时,标记为“离开”
    • 垃圾回收器在运行的时候会给存储在内存中的全部变量都加上标记(固然,可使用任何标记方式)。
    • 而后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)。
    • 而在此以后再被加上标记的变量将被视为准备删除的变量,缘由是环境中的变量已经没法访问到这些变量了。
    • 最后,垃圾回收器完成内存清除工做,销毁那些带标记的值并回收它们所占用的内存空间。
  • 回收方法二:引用计数
    • IE七、8是用的这种方式,不推荐,IE9把DOM和BOM转换为真正的JS对象了,因此再也不使用引用计数
      • IE中的DOM和BOM的实现使用了C++的COM,而COM的回收机制是引用计数
    • 原理:跟踪记录每一个值被引用的次数,当声明一个变量,并将这个引用类型的值赋值给该变量时,这个引用类型值的引用次数就是1
      • var a = {}; // a的引用次数是1
      • 当引用次数变为0时,就会释放该内存值占用的空间
    • 循环引用时会形成内存泄露
      • 循环引用:对象A中包含指向对象B的指针,B中包含指向A的引用,当程序执行结束,引用计数不为0,致使没法释放A、B
      • 解决方案:手动设置为null,切断变量与它此前引用的值之间的链接,GC在下次运行时,就会删除这些值,并把它们回收
  • 浏览器的回收策略--标记清除,可是垃圾收集的时间间隔,各个浏览器互不相同。

内存泄漏的状况

  • 内存泄漏:再也不用到的内存,没有及时释放
  • 引发内存泄露的状况
    • 垃圾回收不会清除全局变量,全局变量会形成内存泄露
      • 缘由:局部变量只在函数的执行过程当中存在,而在这个过程当中会为局部变量在栈或堆上分配相应的空间,以存储它们的值,而后在函数中使用这些变量,直至函数结束,而闭包中因为内部函数的缘由,外部函数结束并不能算是结束。 而全局变量的生命周期直至浏览器卸载页面才会结束。
      • 解决方法:使用严格模式
    • 未销毁的定时器和回调函数,形成内存泄露
      • 定时器的回调函数是个闭包,闭包会形成引用的变量和函数一直保存在内存中,没法释放,形成内存泄露
      • 解决方法:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
    • DOM元素的不恰当处理
      • 虽然别的地方删除了,但对象中仍是存在对DOM的引用,好比引用了td元素,但删除了整个表格,实际上td元素仍然保留对其父元素的引用,致使整个表格都没法回收
      • 解决方法:对于DOM元素的引用要及时手动置空

触发垃圾回收的机制

  • IE6--当环境中存在256个变量、4096个对象、64k的字符串任意一种状况的时候就会触发垃圾回收器工做
    • 当环境中一直存在这么多变量时,GC会一直在工做
  • IE7--触发条件动态修改,根据垃圾回收期回收的内存分配量和程序的内存量比较
  • 垃圾回收时,也没回中止响应,形成页面卡顿,如何优化呢?
    • 方法1:分代回收
      • 变量存储时区分临时、持久区域,多回收临时对象区,少回收持久对象区,减小每次须要遍历的对象,从而减小每次GC耗时
    • 方法2:增量GC
      • 每次处理一点,下次再处理一点,虽然耗时短,可是中断较多,须要上下文频繁切换。
    • 针对不一样场景,能够选择不一样的处理方案

堆内存和栈内存

JS的数据类型有7中,其中Number、Boolean、String、Null、Symbol都是基本类型,Object、Array是引用类型。数组

  • 栈内存保存基本类型的值、指向引用类型的指针,内存大小是固定的
  • 堆内存保存的是引用类型的值,如数组和对象,内存大小是不固定的
  • 栈内存是先进后出,堆内存是按引用地址读取
  • 操做对象时,实际操做的是对象的引用,而不是实际的对象
  • 堆内存由程序员分配,若程序员不释放,程序结束时会有OS回收,分配方式相似链表
  • 栈内存由OS自动操做释放,使用的是一级缓存,被调用时处于存储空间,调用完毕马上释放
  • 堆内存放在二级缓存中,生命周期由垃圾回收算法来决定,并非一旦成为孤儿就会被回收。
相关文章
相关标签/搜索