JavaScript 中的垃圾回收
本文将解释 JavaScript 中垃圾收集的概念。要想了解垃圾回收的必要性,首先要了解内存生命周期
内存生命周期:任何编程语言的内存生命周期都几乎相同,它有 3 个主要步骤。
- 分配内存。
- 使用分配的内存读取或写入或两者兼而有之。
- 不再需要时释放分配的内存。
垃圾收集背后的概述:大多数内存管理问题发生在我们尝试释放分配的内存时。出现的主要问题是确定未使用的内存资源。对于开发人员必须手动决定何时不再需要内存的低级语言, JavaScript等高级语言使用称为垃圾收集 (GC) 的自动内存管理形式。
垃圾收集:以下部分将解释理解主要垃圾收集算法及其局限性所必需的概念。为垃圾收集设计的算法的主要概念是引用的概念。如果前一个对象可以访问后者,则一个对象可以引用另一个对象。例如,一个 JavaScript 对象可以有一个隐式引用(当引用指向它的原型时)和显式引用(当引用指向它的属性值时)。
下面我们将解释用于垃圾收集的算法。
引用计数垃圾收集:该算法被认为是最基本的一种垃圾收集算法。这些算法所做的是,它不是确定任何资源是否重要,而是扫描内存以确定对象是否有任何其他对象引用它。具有零引用的对象被认为是垃圾或“可收集的”。
例子:
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();
- Mark-and-sweep-algorithm:该算法将问题陈述从“不再需要的对象”修改为“无法访问”的对象。该算法需要了解作为一组对象的根的先决条件。在 JavaScript 中,根是一个全局对象。垃圾收集器定期从这些根开始,查找从这些根引用的所有对象,然后查找从这些根引用的所有对象,依此类推。从根开始,垃圾收集器将查找所有可到达的对象,并且标记所有不可到达的对象。
循环不再是问题:函数调用返回后,这两个对象不再被任何可从根对象或全局对象访问的资源引用。因此,这些将被垃圾收集器标记为不可访问,并回收它们分配的内存。
一些限制:可以发现的唯一限制是无法在 JavaScript 中显式或以编程方式触发垃圾收集器。
因此,如果在某些情况下可以方便地手动编程何时释放内存,那么 JavaScript 中没有规定可以触发此类事件。