📜  JavaScript 中的垃圾回收

📅  最后修改于: 2022-05-13 01:56:44.995000             🧑  作者: Mango

JavaScript 中的垃圾回收

本文将解释 JavaScript 中垃圾收集的概念。要想了解垃圾回收的必要性,首先要了解内存生命周期

内存生命周期:任何编程语言的内存生命周期都几乎相同,它有 3 个主要步骤。

  • 分配内存。
  • 使用分配的内存读取或写入或两者兼而有之。
  • 不再需要时释放分配的内存。

垃圾收集背后的概述:大多数内存管理问题发生在我们尝试释放分配的内存时。出现的主要问题是确定未使用的内存资源。对于开发人员必须手动决定何时不再需要内存的低级语言, JavaScript等高级语言使用称为垃圾收集 (GC) 的自动内存管理形式。

垃圾收集:以下部分将解释理解主要垃圾收集算法及其局限性所必需的概念。为垃圾收集设计的算法的主要概念是引用的概念。如果前一个对象可以访问后者,则一个对象可以引用另一个对象。例如,一个 JavaScript 对象可以有一个隐式引用(当引用指向它的原型时)和显式引用(当引用指向它的属性值时)。
下面我们将解释用于垃圾收集的算法。

  1. 引用计数垃圾收集:该算法被认为是最基本的一种垃圾收集算法。这些算法所做的是,它不是确定任何资源是否重要,而是扫描内存以确定对象是否有任何其他对象引用它。具有引用的对象被认为是垃圾或“可收集的”。

    例子:

    javascript
    // Consider the following example
      
    // Declare an object
    var object_1 = {
        object_2: {
            object_3: 7
        }
    };
      
    // In this example, create two objects
    // One object is referred by another 
    // as one of its properties. Currently, 
    // none can be garbage collected
      
    // The "object_4" variable is the second
    // thing that has a reference to the object
    var object_4 = object_1;
      
    // The object that was originally in 
    // "object_1" has a unique reference 
    // embodied by the "object_4" variable
    object_1 = 1;
      
    //Reference to "object_2" property of
    // the object. This object now has 2 
    // references: 1 as a property,
    // The other as the "object_5" variable.
    var object_5 = object_4.object_2;
      
    // The object that was in "object_1" has
    // now zero references to it. It can be 
    // garbage-collected. However its "object_2"
    // property is still  referenced by the
    // "object_5" variable, so it cannot be freed.
    object_4 = "Geeks For Geeks";
      
    // Now the "object_2" property has no 
    // references to it and hence it can
    // be garbage collected.
    object_5 = null;


    javascript
    function Demo() {
        var one = {};
        var two = {};
      
        // one reference to two
        one.object = two;
      
        // two reference to one
        two.object = one;
      
        return 'circular';
    }
      
    Demo();


    障碍:循环引用

    当涉及到循环引用时,就会出现限制。当使用相互引用的属性创建两个对象时,会发生循环引用,从而创建一个循环。
    引用计数算法无法回收这些内存资源,因为每个对象都有至少一个指向它们的引用,这会阻止两个对象都被标记为垃圾回收。循环引用是内存泄漏的主要原因之一。
    下面的示例显示了上述情况的一个实例。

    例子:

    javascript

    function Demo() {
        var one = {};
        var two = {};
      
        // one reference to two
        one.object = two;
      
        // two reference to one
        two.object = one;
      
        return 'circular';
    }
      
    Demo();
    
  2. Mark-and-sweep-algorithm:该算法将问题陈述从“不再需要的对象”修改为“无法访问”的对象。该算法需要了解作为一组对象的的先决条件。在 JavaScript 中,根是一个全局对象。垃圾收集器定期从这些根开始,查找从这些根引用的所有对象,然后查找从这些根引用的所有对象,依此类推。从根开始,垃圾收集器将查找所有可到达的对象,并且标记所有不可到达的对象。

    循环不再是问题:函数调用返回后,这两个对象不再被任何可从根对象或全局对象访问的资源引用。因此,这些将被垃圾收集器标记为不可访问,并回收它们分配的内存。

    一些限制:可以发现的唯一限制是无法在 JavaScript 中显式或以编程方式触发垃圾收集器。
    因此,如果在某些情况下可以方便地手动编程何时释放内存,那么 JavaScript 中没有规定可以触发此类事件。