JS垃圾回收和内存泄露

推荐阅读

问题列表

  • JS垃圾回收有几种方式

  • 什么方式会引起内存泄露

  • 如何避免内存泄漏,有几种方式

  • JS的栈内存和堆内存??堆内存大小是固定的???


1.垃圾回收方式

    JS具有自动垃圾回收机制,GC(Garbage collection会按照固定的时间间隔周期性执行)

    GC不是实时的,因为开销比较大,所以会按照固定的时间间隔周期性执行,各个浏览器的时间间隔不一致

标记清除

  • 当变量进入环境时,标记为“进入环境”,离开环境时,标记为“离开”
  • 垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)
  • 然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)
  • 而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了
  • 最后垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

引用计数

  • IE7、8是用的这种方式,不推荐,IE9把DOM和BOM转换为真正的JS对象了,所以不再使用引用计数

    • IE中的DOM和BOM的实现使用了C++的COM,而COM的回收机制是引用计数

  • 缺点:循环引用时,造成内存泄露

    • 循环引用:对象A中包含指向对象B的指针,B中包含指向A的引用,当程序执行结束,引用计数不为0,导致无法释放A、B

    • 解决方案:手动设置为null,切断变量与它此前引用的值之间的连接,GC在下次运行时,就会删除这些值,并把它们回收

  • 原理:

    • 跟踪记录每个值被引用的次数,当声明一个变量,并将这个引用类型的值赋值给该变量时,这个引用类型值的引用次数就是1,当引用次数变为0时,就会释放该内存值占用的空间

    • var a = {}; // a的引用次数是1

  • 现代浏览器的回收策略--标记清除,但是垃圾收集的时间间隔互不相同

2.栈内存和堆内存

  • 栈内存保存基本类型的值、和指向引用类型的指针,内存大小是固定的

  • 堆内存保存的是引用类型的值,如数组和对象,内存大小是不固定的

  • 栈内存是先进后出,堆内存是按引用地址读取

  • 操作对象时,实际操作的是对象的引用,而不是实际的对象

  • 堆内存由程序员分配,若程序员不释放,程序结束时会有OS回收,分配方式类似链表

  • 栈内存由OS自动操作释放,使用的是一级缓存,被调用时处于存储空间,调用完毕立刻释放

  • 堆内存放在二级缓存中,生命周期由垃圾回收算法来决定,并不是一旦成为孤儿就会被回收

3.触发垃圾回收的设置?

  • IE6--当环境中存在256个变量、4096个对象、64k的字符串任意一种情况的时候就会触发垃圾回收器工作
  • 缺点:现代网站都比较复杂,JS中的变量较多,当环境中一直存在这么多变量时,GC会一直在工作,那网站就没办法工作了
  • IE7--触发条件动态修改,根据垃圾回收的内存分配量和程序的内存量比较
  • GC时,停止响应,会造成页面卡顿,如何优化呢?
    • 分代回收方法--变量存储时区分临时、持久区域,多回收临时对象区,少回收持久对象区,减少每次需要遍历的对象,从而减少每次GC耗时
    • 增量GC方法--每次处理一点,下次再处理一点,虽然耗时短,但是中断较多,需要上下文频繁切换

4,内存泄露

  • 定义:不再用到的内存,没有及时释放,就叫做内存泄漏

  • 引起内存泄露的情形

    • 垃圾回收不会清除全局变量,全局变量会造成内存泄露,解决方法--使用严格模式

    • 未销毁的定时器和回调函数,造成内存泄露

      • 定时器的回调函数是个闭包,闭包会造成引用的变量和函数一直保存在内存中,无法释放,造成内存泄露

      • 将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。

    • DOM元素的不恰当处理

      • 对于DOM元素的引用要及时手动置空

      • 虽然别的地方删除了,但对象中还是存在对DOM的引用,比如引用了td元素,但删除了整个表格,实际上td元素仍然保留对其父元素的引用,导致整个表格都无法回收

5.WeakMap--对于值的引用不计入垃圾回收机制,表示是弱引用

  • 只要外部的引用消失,WeakMap 内部的引用,就会自动被垃圾回收清除。

6.如何观测内存泄露

  • Google/Timeline面板,鼠标操作,录制视频,观测折线图,曲折、抖动则有内存泄露

  • Node--process.memoryUsage()

    • * rss(resident set size):所有内存占用,包括指令区和堆栈。

    • * heapTotal:"堆"占用的内存,包括用到的和没用到的。

    • * heapUsed:用到的堆的部分。

    • * external: V8 引擎内部的 C++ 对象占用的内存。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值