什么是JavaScript垃圾收集?

什么是JavaScript垃圾收集?为了编写更好的代码,web程序员了解JavaScript垃圾收集的重要方面是什么?

124903 次浏览

什么是JavaScript垃圾收集?

检查

对于web程序员来说,了解JavaScript垃圾收集的重要一点是, 为了写出更好的代码?< / p >
在Javascript中,你不关心内存分配和释放。整个问题都需要Javascript解释器来解决。在Javascript中泄漏仍然是可能的,但它们是解释器的错误。如果你对这个话题感兴趣,你可以阅读更多 www.memorymanagement.org < / p >

Eric Lippert不久前写了一个关于这个主题的详细博文(另外将它与VBScript进行比较)。更准确地说,他写了< em > JScript < / em >,这是微软自己的ECMAScript实现,尽管与JavaScript非常相似。我可以想象,您可以假设Internet Explorer的JavaScript引擎的绝大多数行为是相同的。当然,实现因浏览器而异,不过我认为您可以将一些常见原则应用于其他浏览器。

引自该页:

JScript使用非分代 标记-清除垃圾收集器。它 工作原理如下:

  • “在范围内”的每个变量 被称为“拾荒者”。一个拾荒者 可以指一个数字,一个物体,一个 字符串,等等。我们有一个列表 清除程序——变量被移动 等他们来了,就在扫荡名单上 进入扫荡范围,然后离开扫荡名单 它们超出范围。

  • Every now and then the garbage 收集器运行。首先它放了一个 在每个对象、变量、 字符串,等等-所有的内存跟踪 被GC。(JScript使用VARIANT 数据结构内部和那里 是否有大量多余的未使用的比特 这个结构,我们只要设一个 李。)< / p > < / >

  • 其次,它清除上的标记 清除器和传递闭包 清道夫的引用。如果a 清除器对象引用 非清除者对象,然后清除 在非清道夫上,然后在上面 它指的所有东西。(我 使用“终结”这个词 和我之前的感觉不一样 李。)< / p > < / >

  • 至此我们知道所有的 仍然标记的内存已被分配 无法触及的记忆 任何范围内变量的路径。所有 这些对象的指令 把自己拆了,这就是毁灭 任何循环引用。

垃圾收集的主要目的是允许程序员担心他们创建和使用的对象的内存管理,当然有时无法避免——至少对垃圾收集的工作方式有一个粗略的了解总是有益的。

历史的注意:答案的早期修订有一个不正确的引用delete操作符。在JavaScript中delete操作符从对象中移除一个属性,与C/ c++中的delete完全不同。

当涉及到DOM对象时,要注意循环引用:

JavaScript中的内存泄漏模式

请记住,只有在没有对对象的活动引用时才能回收内存。这是闭包和事件处理程序的一个常见陷阱,因为一些JS引擎不会检查内部函数中实际引用了哪些变量,而只是保留封闭函数的所有局部变量。

这里有一个简单的例子:

function init() {
var bigString = new Array(1000).join('xxx');
var foo = document.getElementById('foo');
foo.onclick = function() {
// this might create a closure over `bigString`,
// even if `bigString` isn't referenced anywhere!
};
}

只要事件处理程序存在,简单的JS实现就不能收集bigString。有几种方法可以解决这个问题,例如在init()的末尾设置bigString = null (delete不适用于局部变量和函数参数:delete会从对象中删除属性,并且变量对象不可访问——如果你试图删除局部变量,ES5在严格模式下甚至会抛出ReferenceError !)

如果您关心内存消耗,我建议尽可能避免不必要的闭包。

这句话摘自博客

DOM组件是“垃圾收集”的,JScript组件也是如此,这意味着如果您在任何一个组件中创建了一个对象,然后失去了对该对象的跟踪,它最终将被清除。

例如:

function makeABigObject() {
var bigArray = new Array(20000);
}

当您调用该函数时,JScript组件将创建一个可以在函数中访问的对象(名为bigArray)。但是,一旦函数返回,您就会“失去跟踪”bigArray,因为再也没有办法引用它了。JScript组件意识到您已经失去了对它的跟踪,因此bigArray被清理——它的内存被回收。DOM组件中也有类似的工作。如果你说document.createElement('div'),或类似的东西,那么DOM组件为你创建一个对象。一旦您以某种方式失去了该对象的跟踪,DOM组件将清理相关的。

据我所知,JavaScript的对象在没有对对象的引用时周期性地进行垃圾收集。这是自动发生的事情,但如果你想了解更多关于它是如何工作的,在c++级别,看一下WebKitV8源代码是有意义的

通常你不需要考虑这一点,但是,在较老的浏览器中,如IE 5.5和早期版本的IE 6,也许还有当前版本,闭包会创建循环引用,如果不勾选的话,最终会消耗内存。在我指的闭包的特殊情况下,它是当您将JavaScript引用添加到dom对象,并将对象添加到dom对象,后者引用回JavaScript对象。基本上,它永远不会被收集,最终会导致操作系统在测试应用程序中变得不稳定,从而导致崩溃。实际上,这些泄漏通常很小,但为了保持代码干净,应该删除对DOM对象的JavaScript引用。

通常,使用delete关键字立即取消对JSON数据等大对象的引用是一个好主意,特别是在移动web开发中。这将导致GC的下一次扫描删除该对象并释放其内存。

在计算机科学中,垃圾收集(GC)是自动内存管理的一种形式。垃圾收集器,或者仅仅是垃圾收集器,尝试回收垃圾或对象所使用的内存,这些对象将永远不会被应用程序再次访问或更改。”

所有JavaScript引擎都有自己的垃圾收集器,它们可能有所不同。大多数时候你不需要和他们打交道,因为他们只是在做他们应该做的事情。

写出更好的代码主要取决于你对编程原理、语言和特定实现的了解程度。

在windows中,你可以使用Drip.exe来查找内存泄漏或检查free mem例程是否工作。

这真的很简单,只要输入一个网站的URL,你就会看到集成IE渲染器的内存消耗。然后点击刷新,如果内存增加,你在网页的某个地方发现了内存泄漏。但这也非常有用,看看释放内存的例程是否适用于IE。

垃圾收集(GC)是通过删除不再需要的对象来自动进行内存管理的一种形式。

任何处理内存的进程都遵循以下步骤:

1 -分配你需要的内存空间

2 -做一些处理

3 -释放这个内存空间

有两种主要的算法用于检测哪些对象不再需要。

引用计数垃圾收集:此算法将“一个对象不再需要”的定义简化为“一个对象没有其他对象引用它”,如果没有引用点指向该对象,则该对象将被删除

标记和清扫算法:将每个对象连接到根源。任何对象都不连接根或其他对象。该对象将被移除。

目前大多数现代浏览器使用第二种算法。

引用类型不直接将对象存储到变量to中 它被赋值了,下面例子中的对象变量,实际上没有 包含对象实例。相反,它持有指向的指针(或引用)

.内存中对象存在的位置
var object = new Object();

如果你将一个引用类型的变量赋值给另一个,每个变量 获取指针的副本,两者仍然引用中相同的对象 记忆。< / p >

var object1 = new Object();
var object2 = object1;

两个变量指向一个对象

JavaScript是一种垃圾收集语言,所以你真的不需要 使用引用类型时,要考虑内存分配问题。然而, 最好是废弃对象,你不再需要,以便垃圾 收集器可以释放该内存。最好的方法是设置

.对象变量为空
var object1 = new Object();
// do something
object1 = null; // dereference

非关联化对象在使用数百万个对象的大型应用程序中尤其重要。

摘自《面向对象的JavaScript原则》——NICHOLAS C. ZAKAS

在javascript中,垃圾收集是不确定的,对象何时会被清除,或者是否会被清除。这适用于强引用的对象。强引用对象不受垃圾回收的影响。

在ES12之后,可以执行以下实现来检查对象何时被垃圾收集。

要了解更多关于javascript垃圾收集的知识,你可以使用ES12之后可用的终结器。

let a = new Array(200).fill(true);

构造定稿器

const cleanup = new FinalizationRegistry(key => {
// your code here
});


cleanup.register(a, 'wewew');

对象'a'现在不可达,终结器回调将在垃圾收集后发生