javascript是广泛应用于现代web开发的一门编程语言,这门语言的垃圾回收机制是我们经常需要考虑优化的部分之一。
在javascript中,垃圾回收机制是对不再被引用的对象自动清理的过程。在浏览器中,这些不再被引用的对象占用着不必要的内存资源,会严重影响应用的性能表现。
一个常见的垃圾回收机制就是引用计数垃圾回收。如果一个对象被引用,其计数值加1,如果出现另一个引用则计数值加1。相应的,如果一个对象的计数器为零,则它不再被使用,处理机制会自动清理它。
var obj1 = { }; var obj2 = { }; var obj3 = { }; // 设置两个变量引用同一个对象 obj1.ref = obj2; obj2.ref = obj1; // 现在,两个对象都有计数器值为2;
然而,这种引用计数的垃圾回收机制也有缺点。比如这份代码:
var obj1 = { }; var obj2 = { }; // 设置两个变量引用同一个对象 obj1.ref = obj2; obj2.ref = obj1; // 原本是两个对象都有计数器值为1; // 但现在,由于语义问题,计数器上没有任何引用;
在这种情况下,垃圾回收机制就需要自动检测这种语义上的问题并判断是否有必要清理这个对象。而这需要消耗更多的计算机资源。
当然,javascript的垃圾回收机制还有其他类型。其中最常见的是标记清理和引用计数。标记清理的工作流程如下:
- 垃圾回收器创建一个“根”列表。这些根都存储在全局执行上下文中。
- 垃圾回收器在根列表中查找所有对象。
- 垃圾回收器标记指向这些根对象的所有对象。
- 垃圾回收器从根对象起,依次递归访问引用对象、内部引用,直到所有可到达的对象都被访问之后,清楚未标记的对象。
如同上面所提到的缺陷一样,标记清理也可能会因对象拥有的隐式引用而误判可用性。
好消息是,浏览器和javascript引擎的开发者们一直在不断提升对于垃圾回收机制的优化。使用“object pooling”、“composable allocation”、“generational scavenging”等技术方法,可以将原本长期执行的GC流程缩短,同时提高性能和内存利用率。
JavaScript的垃圾回收器通过跟踪对象引用的方式进行工作并自动回收未被使用的内存,帮助我们减少出错和加快代码执行速度。我们需要了解这个特性的内部实现和调整策略来优化js性能。