Skip to main content
 首页 » 编程设计

Javascript 垃圾回收

2022年07月19日157lonelyxmas

Javascript 垃圾回收

内存管理Javascript是自动完成的,对用户来说是透明的。我们创建原始类型、对象、函数等,所有这些都需要占用内存。当一些对象不再被需要时,Javascript引擎是如何发现并清除?

能达性(Reachability)

Javascript内存管理主要概念是能达性。简单说,“能达”是那些可被访问或使用值,他们需保证存储在内存中。
1、继承可达值,他们显然不能被删除。

  • 当前函数中局部变量和参数
  • 在当前嵌套调用链的其他函数使用的变量或参数
  • 全局变量

2、从一个根引用或引用链可到达的值。
如一个对象有内部变量被另一个对象的属性引用,则该对象是能到达的。

Javascript引擎有后台进程称为垃圾回收,它监控所有对象并删除那些不可到达的对象。

示例1

// user has a reference to the object 
let user = { 
  name: "John" 
}; 
 
user = null; 

这里全局对象user引用对象{name:”John”},如果user被重写,则引用丢失,现在对象{name:”John”}变得不可达,没有办法访问,没有引用指向它,垃圾回收程序将丢弃数据释放内存。

// user has a reference to the object 
let user = { 
  name: "John" 
}; 
 
let admin = user; 
 
user = null; 

这段代码,有两个引用指向对象,删除一个,仍然有admin指向对象,因此对象不会被回收。

相互链接对象

看下面一个复杂的示例

function marry(man, woman) { 
  woman.husband = man; 
  man.wife = woman; 
 
  return { 
    father: man, 
    mother: woman 
  } 
} 
 
let family = marry({ 
  name: "John" 
}, { 
  name: "Ann" 
}); 

函数marry缔结两个对象,两个对象之间相互引用,然后返回一个新对象包含他们一起,内存结构如下:

现在所有对象都可到达,现在删除变量。

delete family.father; 
delete family.mother.husband; 


删除其中任何一个都不能Johe对象(简写)不可到达,但现在删除两个,我们能看到John对象不再有输入引用。

向外引用不重要,只有输入引用会让对象可达。所以John对象现在不能到达,将被垃圾回收,其所有数据也不能被访问。回收后内存结构如下:

孤岛

相互链接的孤岛对象可能变成不可到达,同样也会被回收,下面代码示例:

family = null; 

内存结构变成:

显然John对象和Ann对象相互引用,互为输入引用,但这是不够的,family对象已经从根断开,不再有引用指向孤岛对象,所有整个孤岛将被回收。内部算法这里不再详述。

总结

  • 垃圾回收是自动执行的,我们无法阻止。
  • 当对象是可到达时,保留在内存中。
  • 被引用与可到达不同(从一个根),如相互引用对象整体不能到达。

现代引擎如V8实现了垃圾回收的高级算法,优化性能,快速准确回收。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/68483119