1、内存分配场景
JavaScript中主要是根据数据类型区分,主要有以下的七种数据类型,几乎涵盖所有运用场景。
- 简单数据类型
- 基本包装类型
- 对象类型
- 数组类型
- 函数类型
- 其他常用对象
- 闭包
闭包的定义:函数内部的函数,并且内部函数可以访问外部函数的变量。闭包的主要作用是进行代码隔离。
2、内存回收规则
- 全局变量:当页面被关闭,内存才会被回收
- 局部变量:当函数执行完,内存才会被回收
- 闭包:局部变量的特殊情况,局部变量会被内部函数所占用(引用),就算外部函数执行完成,也不一定会被回收。
3、垃圾回收机制GC的原理及性能优化
标记清除
在变量声明时标记为【进入环境】,当变量使用完成时,标记为【离开环境】,【离开环境】标记的变量将等待被回收。
全局变量在声明时标记为【进入环境】,直到页面关闭时,才标记为【离开环境】,因此,全局变量只有在页面关闭时才会回收;局部变量在函数内部定义时,标记为【进入环境】,在函数执行结束后,就标记为【离开环境】,因此,在函数执行结束后,局部变量就等待被回收。
标记清除的缺点:某些对象被清理后,内存是不连续的。那么就算内存占用率不高,只有50%,但是由于内存空隙太多,后来的大对象无法存储到内存之中。
标记清除缺点的解决方案:在垃圾回收后进行整理操作,这种操作叫做标记整理。就是将不连续的内存向一端复制,使不连续的内存连续起来。
引用计数
跟踪记录每个值被引用的次数。当值的引用次数变为0,说明没有办法再访问这个值,因而可以将其占用的空间回收。当垃圾回收器下次运行时,就会释放那些引用次数为0的值所占用的空间。
主要缺点:存在循环引用的情况,此种情况下,不存在引用次数为0的情况。
解决方案:将引用计数策略换成标记清除策略。
解除引用
一旦数据不再有用,最好通过将其值置为null来释放引用,这一做法适用于大多数的全局变量和局部对象的属性,局部变量会在它们离开执行环境时自动解除引用。
解除一个值的引用并不意味着自动回收该值所占用的内存,解除引用的真正作用是让值脱离执行环境,以便垃圾回收器下次运行时将其回收。
GC的性能优化
引擎需要优化的原因:避免垃圾回收造成的长时间的停止响应。
解决方案:分代回收以及增量回收
分代回收
分代回收是基于以下的假设所设计的
- 对象越新,生存期越短
- 对象越老,生存期越长
- 回收内存的一部分,速度快于回收整个内存
多回收新增对象区,少回收持久对象区,减少每次需要遍历的对象,从而减少垃圾回收的时间。
增量回收
即每次处理一点儿,下次再处理一点儿,分多次回收,以此类推。垃圾回收与应用逻辑交替执行。
增量回收中常采用惰性清理:延迟清理过程,等需要分配内存时再来清理,可进一步提高垃圾回收的效率。
内存的调试技巧
Memory面板及建立快照,对比所使用的内存,可以看到哪个对象所占用内存多导致内存泄漏。