总结

  1. 垃圾回收程序必须跟踪记录哪个变量还会使用,以及哪个变量不会再使用,以便回收 内存。
  2. 如何标记未使用的变量,在浏览器的发展史上,用到过两种主要的 标记策略:标记清理和引用计数。
  3. 最常用的垃圾回收策略是标记清理,垃圾回收程序运行时,会标记内存中所有储存的变量,然后,它会把所有在上下文,以及被在上下文中的变量引用的变量的标记去掉;在此之后被加上标记的变量为待删除(原因是任何上下文都访问不到它们了,这些变量没有被引用),随后垃圾回收程序做一次内 存清理,销毁带标记的所有值并收回它们的内存。
  4. 另一种没那么常用的垃圾回收策略是引用计数(reference counting)。思路是对每个值都记录它被 引用的次数。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。image.png
  5. 引用计数的缺点,不能循环引用,引用计数不会清零,退出上下文后,变量还是会保存在内存中image.png
  6. IE9 把 BOM 和 DOM 对象都改成了 JavaScript 对象,这同时也避免了由于存在两 套垃圾回收算法而导致的问题,还消除了常见的内存泄漏现象。
  7. 性能:垃圾回收程序会周期性运行,遵从一个原则:无论什么时候开始 收集垃圾,都能让它尽快结束工作。现代垃圾回收程序会基于对 JavaScript 运行时环境的探测来决定何时运行。探测机制因引擎而异,基本上都是根据已分配对象的大小和数量来判断的。根据 V8 团队 2016 年的一篇博文的说法: “在一次完整的垃圾回收之后,V8 的堆增长策略会根据活跃对象的数量外加一些余量来确定何时再次垃圾回收。”
  8. IE是根据变量的个数,对象/数组的个数,槽位或者字符串所点的内存,达到某个条件,垃圾回收程序就会运行。问题在于,在其整个生命周期内始终需要那么多变量,结果就会导致垃圾回收程序过于频繁地运行;IE7的改变:如果垃圾回收程序回收的内存不到已分配的 15%, 这些变量、字面量或数组槽位的阈值就会翻倍(说明需要比较多的变量,调整阈值,就减少了垃圾回收程序的运行次数)。如果有一次回收的内存达到已分配的 85%,则阈值重置 为默认值。这么一个简单的修改,极大地提升了重度依赖 JavaScript 的网页在浏览器中的性能。
  9. 分配给浏览器的内存通常比分配给桌面软件的要少很多,分配给移动 浏览器的就更少了。这更多出于安全考虑而不是别的,就是为了避免运行大量 JavaScript 的网页耗尽系 统内存而导致操作系统崩溃。
  10. 将内存占用量保持在一个较小的值可以让页面性能更好。(优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据),把不再用到的数据设置为null,这个是解除引用(解除引用的关键在于确保相关 的值已经不在上下文里了,因此它在下次垃圾回收时会被回收。)
  11. 通过 const 和 let 声明提升性能(原因:以块(而非函数)为作用域,所以相比于使用 var,使用这两个新关键字可能会更早地让垃圾回 收程序介入,尽早回收应该回收的内存。在块作用域比函数作用域更早终止的情况下,这就有可能发生。)
  12. 两个实例共享同一个构造函数和原型,V8 会在后台配置,让这两个类实例共享相同的隐藏类,能够共享相同隐藏类 的对象性能会更好,V8 会针对这种情况进行优化。image.png如果要删除某个属性,把属性值设置为null,这样可以保持隐藏类不变 和继续共享,同时也能达到删除引用值供垃圾回收程序回收的效果。使用 delete 关键字会导致生成相同的隐藏类片段image.png
  13. 可能造成成内存泄露的原因:1.在函数里的变量没有声明;2.定时器一直运行,定时器回调里的变量不被回收;3.闭包函数一起存在,函数内部声明的变量就不会被回收image.pngimage.pngimage.png

问题

垃圾回收只是有了初步的了解,并没有深入的学习