栈空间和堆空间:数据是如何存储的?
javascript 是什么类型的语言
静态语言:在使用之前就需要确认其变量数据类型的。 动态语言:在运行过程中需要检查数据的类型的语言。
弱类型,动态的语言。
弱类型: 不需要告诉javascript引擎这个或那个变量是什么数据类型,javascript引擎在运行代码的适合会计算。
动态 :可以使用同一个变量保存不同类型的数据。
注: typeof Null === Object
这是一个遗留问题。
上述前面七种称为 原始类型 ,最后一个对象称为 引用类型 。
栈空间和堆空间
原始类型的数据值都是直接保存在 栈 中的,引用类型的值是存放在 堆 中的。
原始类型的赋值 会完整复制变量值,引用类型的赋值 是复制引用地址。
原因:javascript 引擎需要用栈来维护程序执行期间上下文的状态,如果栈空间大了的话,所有的数据都存放在栈空间里面,那么会影响到上下文切换的效率,进而影响到整个程序的执行效率。
闭包的内存模型
垃圾回收:垃圾数据是如何自动回收的
不同语言的垃圾回收策略
- 手动回收
- c/c++ ,何时分配内存,何时销毁内存都是由代码控制的
- 自动回收
- 如 javascript Java 产生的垃圾数据是由垃圾回收器来释放的
调用栈中的数据是如何回收的
ESP : 记录当前执行状态的指针
堆中的数据是如何回收的
代际假说和分代收集
代际假说的特点:
一:大部分对象在内存中存在的时间很短,简单来说就是很多对象一经分配内存,很快就变得不可访问
二:不死的对象,会活的更久
V8会把堆中分为 新生代 和 老生代 两个区域
新生代存放的是生存时间短的对象,老生代中存放的生存时间久的对象。
副垃圾回收器,主要负责新生代的垃圾回收
主垃圾回收器,主要负责老生代的垃圾回收
垃圾回收器的工作流程
不论什么类型的垃圾回收器,都有一套共同的执行流程
1.标记空间中活动对象和非活动对象,所谓活动对象就是还在使用的对象,非活动对象就是可以进行垃圾回收的对象
2.回收非活动对象所占据的内存,其实就是在所有的标记完成之后,统一清理内存中所有被标记为可回收的对象
3.内存整理。一般来说,频繁回收对象后,内存中就会存在大量不连续空间,我们 把这些不连续的内存空间称为内存碎片。当内存中出现了大量的内存碎片之后,如果需要分 配较大连续内存的时候,就有可能出现内存不足的情况。所以后一步需要整理这些内存碎 片,但这步其实是可选的,因为有的垃圾回收器不会产生内存碎片,比如接下来我们要介绍 的副垃圾回收器。
副垃圾回收器
新生代中用 Scavenge 算法来处理。即 把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域
主垃圾回收器
全停顿
现在你知道了 V8 是使用副垃圾回收器和主垃圾回收器处理垃圾回收的,不过由于 JavaScript 是运行在主线程之上的,一旦执行垃圾回收算法,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。我们把这种行为叫做全停顿(Stop-The-World)