PHP开源Hub
致力于开发者的提升

[译] 通过垃圾回收机制理解 JavaScript 内存管理

内存管理的主要目标是在需要的时候为系统动态地分配内存,然后释放那些不再使用的对象的内存。像 C 和 C++ 这样的语言有基本的内存分配函数,如 malloc(),而一些高级语言计算机体系结构(如 JavaScript)包含垃圾回收器来完成这项工作。它跟踪内存分配并识别这些分配的内存是否不再使用,如果是就自动释放。但是这种算法不能完全决定内存是否仍被需要。因此,对于程序员来说,理解并决定一段特定的代码是否需要内存是非常重要的。让我们了解一下 JavaScript 中的垃圾收集是如何工作的:

垃圾回收

JavaScript 引擎的垃圾回收器基本上是寻找内存中被删除的无法访问的对象。这里我想解释两种垃圾回收算法,如下所示:

  • 引用计数垃圾回收
  • 标记清除算法

引用计数垃圾回收

这是一个简单的垃圾回收算法。这个算法寻找那些没有被引用的对象。如果一个对象没有被引用,那么该对象就可以被垃圾回收。

var obj1 = {
    property1: {
         subproperty1: 20
     }
};
复制代码

如上例所示,让我们创建一个对象以理解这个算法。这里 obj1 引用了一个对象,其中的 property1 属性也引用了一个对象。由于 obj1 具有对象的引用,因此这个对象不会被垃圾回收。

var obj2 = obj1;

obj1 = "some random text"
复制代码

现在,obj2 也引用了被 obj1 引用的同一个对象,但后来 obj1 被更新为了 "some random text",这导致 obj2 具有对该对象的唯一引用。

var obj_property1 = obj2.property1;
复制代码

现在 obj_property1 指向 obj2.property1,它引用了一个对象。因此该对象有两个引用,如下所示:

  1. 作为 obj2 的属性
  2. 在变量 obj_property1
obj2 = "some random text"
复制代码

通过更新为 "some random text" 来取消 obj2 对对象的引用。因此,之前的这个对象似乎没有被引用了,所以它可以被垃圾回收。但是,由于 obj_property1 具有 obj2.property1 的引用,因此它不会被垃圾回收。

obj_property1 = null;
复制代码

当我们把 obj_property1 引用删除,现在最初 obj1 指向的对象没有引用了。所以现在它可以被垃圾回收。

这个算法在哪里失败了?

function example() {
     var obj1 = {
         property1 : {
              subproperty1: 20
         }
     };
     var obj2 = obj1.property1;
     obj2.property1 = obj1;
     return 'some random text'
}

example();
复制代码

这里引用计数算法在函数调用之后不会从内存中删除 obj1obj2 ,因为两个对象都是相互引用的。


标记清除算法

这个算法查找从根开始无法访问的对象,这个根是 JavaScript 的全局对象。该算法克服了引用计数算法的局限性。没有引用的对象是不可访问的,但是反过来就不一定了。

var obj1 = {
     property1: 35
}
复制代码

如上所示,我们可以看到创建的对象 obj1 如何从 ROOT 中访问到的。

obj1 = null
复制代码

现在,当我们将 obj1 的值设置为 null 时,该对象从根开始无法被访问,因此它可以被垃圾回收。

该算法从根开始,遍历所有其他对象,同时标记它们。它进一步遍历被遍历的对象并标记它们。这个过程将被重复直到所有已被遍历的节点没有任何子节点和可遍历的路径。现在垃圾回收器会忽略所有可访问对象,因为它们在遍历时被标记。因此,所有未标记的对象显然都是从根节点开始无法访问的,这意味着它们可以被垃圾回收,稍后通过删除这些对象释放内存。让我们通过下面的例子来试着理解一下:

如上所示,这就是对象结构的样子。我们可以注意到无法从根开始访问的对象,但是让我们尝试了解在这种情况下标记清除算法是如何工作的。

算法从根开始标记遍历到的对象。上面的图片中,我们可以注意到在对象上标记的绿色圆圈。这样它就可以将对象标识为可从根开始可以访问到。

未被标记的对象是无法从根开始被访问到的。因此它们可以被垃圾回收。

局限性

对象必须显式地设置为不可访问。

自 2012 年以来,JavaScript 引擎已经使用此算法来代替引用计数垃圾回收。

谢谢阅读。


作者:wuzhengyan2015
来源:掘金

赞(0) 打赏
未经允许不得转载PHP开源Hub » [译] 通过垃圾回收机制理解 JavaScript 内存管理

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

PHP开源Hub-致力于互联网开发者的成长

技术群聊软文发表

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏