v8执行js代码的过程
1.将源代码生成抽象语法树AST:源代码进行词法分析和语法分析后生成AST
2.生成字节码:根据AST生成字节码,字节码通过解释器转换为机器码才能执行
3.执行代码:如果一段字节码是第一次执行,解释器会逐行执行;如果在执行字节码过程中发现有热点函数,JIT即时编译器就会把热点函数编译为机器码,并保存起来,下次就可以直接使用了,省去了将字节码转换为机器码的过程,提升了执行效率
垃圾回收
新生代内存回收
新生代中用 Scavenge 算法来处理。所谓 Scavenge 算法,是把新生代空间对半划分为两个区域,一半是对象区域(from),一半是空闲区域 (to)。
老生代内存回收
新生代中多次进行回收仍然存活的对象会被转移到空间较大的老生代内存中,这种现象称为晋升。以下两种情况:
- 在垃圾回收过程中,发现某个对象之前被清理过,那么将会晋升到老生代的内存空间中
- 在 from 空间和 to 空间进行反转的过程中,如果 to 空间中的使用量已经超过了 25% ,那么就讲 from 中的对象直接晋升到老生代内存空间中。
标记-清除(Mark-Sweep)
标记-整理(Mark-Compact)
增量标记
回答问题
哪些操作会造成内存泄漏?
-
意外的全局变量:无法被回收
-
被遗忘的定时器或回调函数:导致所引用的外部变量无法被释放
-
脱离 DOM 的引用:dom 元素被删除时,内存中的引用未被正确清空
-
闭包:会导致父级中的变量无法被释放
参考:
[译] 通过垃圾回收机制理解 JavaScript 内存管理
【JSConf EU 2018】JavaScript引擎: 精粹部分