JavaScript和垃圾回收

47

有没有办法控制 JavaScript 执行垃圾回收的时机?我想在特定的时间启用垃圾回收,以确保我的网站顺畅运行。


1
总之,不行。这对许多网站来说并不是问题。也许您可以更详细地解释一下您的问题是什么? - user1864610
4
高性能、垃圾回收友好的代码在编写JavaScript代码时,高效利用内存是至关重要的。这篇文章将介绍一些编写高性能、垃圾回收友好的JavaScript代码的技巧。1.使用对象池来避免频繁的内存分配和垃圾回收。2.尽可能使用弱映射和弱集合,因为它们可以帮助减少内存占用并促进垃圾回收。3.当需要从数组中删除元素时,可以将该元素替换为数组末尾的元素,然后删除末尾元素。这样做可以避免创建新的数组实例。4.避免在全局作用域中声明变量,这会导致垃圾回收器无法释放不再需要的变量。5.使用闭包时,尽可能避免创建循环引用。循环引用可能会导致内存泄漏,而闭包对于垃圾回收来说是一个复杂的问题。6.避免使用eval()函数,因为它会导致代码动态生成并且难以优化。通过遵循这些技巧,您可以编写出更快、更节省内存的JavaScript代码,从而提高应用程序的性能。 - raina77ow
2
为什么要踩我?我有几个不错的参考资料可以阅读。 - Ed Heal
2
当使用node时,您可以使用v8选项“--expose_gc”运行node app,然后可以简单地调用函数“gc()”。我在问题v8 | manually initiate the garbage collector中找到了这个答案。 - shawnzhu
显示剩余2条评论
6个回答

80

Javascript没有显式的内存管理,是浏览器决定何时清理内存。有时候你可能会因为垃圾回收暂停而遇到JavaScript渲染不流畅的情况。

有许多技巧可以应用来克服由垃圾回收(GC)引起的故障。您应用越多,探索得就越多。假设您在JavaScript中编写了一个游戏,每秒钟都要创建一个新对象,那么显然在一定时间后将出现GC,以获得更多空间用于您的应用程序。

对于像需要大量空间的实时应用程序(如游戏)来说,你可以做的最简单的事情是重复使用相同的内存。这取决于您如何构造代码。如果它产生大量垃圾,则可能会给人带来不流畅的体验。

通过使用简单的过程:众所周知,new关键字表示分配。在可能的情况下,您可以尝试通过每次添加或修改属性来重复使用相同的对象。这也称为 对象的回收

在数组的情况下,赋值[]通常用于清除数组,但您应该记住它也会创建一个新数组并且垃圾旧数组。为了重复使用相同的块,您应该使用arr.length = 0。这具有相同的效果,但它重复使用相同的数组对象而不是创建新对象。

在函数的情况下:有时我们的程序需要定期使用setInterval或setTimeout调用特定的函数。

ex: setTimeout(function() { doSomething() }, 10);

你可以通过将函数分配给永久变量而不是在常规间隔时间内每次生成来优化上述代码。

    ex : var myfunc = function() { doSomething() }
    setTimeout(myfunc, 10);

另一个可能的情况是,数组的slice()方法返回一个新的数组(基于原始数组中的一段范围,可以保持不变),字符串的substr也返回一个新的字符串(基于原始字符串中的一段字符范围,可以保持不变),等等。如果没有正确地重新利用这些函数调用,则会创建垃圾。

在JavaScript中完全避免垃圾非常困难,甚至可以说是不可能的。它取决于如何重复使用对象和变量以避免垃圾。如果您的代码结构良好且经过优化,可以最小化开销。


1
如果你要做所有这些,用C++编写游戏并通过Emscripten编译为asm.js会更好吧?不需要担心垃圾回收 :) - Demi

5
很遗憾,无法控制垃圾回收的时间,但通过正确构建对象,可以控制垃圾回收的速度和效率。请参考Mozilla Dev Net上的这些文档
引用:
该算法假定已知一组称为根的对象(在JavaScript中,根是全局对象)。周期性地,垃圾回收器将从这些根开始,找到所有从这些根引用的对象,然后找到所有从这些对象引用的对象等等。从根开始,垃圾回收器因此会找到所有可达对象并收集所有不可达对象。
该算法比以前的算法更好,因为“一个对象没有引用”会导致该对象变得不可达。相反的情况则不成立,正如我们在循环中看到的那样。

只有全局对象是根对象吗? 那函数执行上下文中的堆栈变量呢? 它们也会引用堆内存。 当函数结束时,堆栈上的引用被移除,但内存仍然保留在堆中。 - undefined

2
为什么不将对象的引用保留到你想让它们被垃圾回收的时候再释放?
var delayed_gc_objects = [];
function delayGC(obj) { // keeps reference alive
    return delayed_gc_objects[delayed_gc_objects.length] = obj;
}
function resumeGC() { // kills references, letting them be GCd
    delayed_gc_objects.length = 0;
}

10
这只是延迟回收(扫描),而不是可达性检查(跟踪),更不用说整个垃圾回收了。换句话说,这只会浪费垃圾回收的时间。 - user395760

0

您可以进行一些更改来改善内存使用,例如:

  1. 不要在循环中设置变量
  2. 避免使用全局变量和函数。它们会占用一部分内存,直到您退出。

0

JavaScript 是一种垃圾回收语言,这意味着执行环境负责管理代码执行期间所需的内存。 JavaScript 最流行的垃圾回收形式称为标记和清除。 第二种不那么流行的垃圾回收方式是引用计数。其思想是每个值都跟踪了对它进行了多少个引用。

即使您设法触发了垃圾回收机制,也不能保证它会立即运行,只是将其标记。


由于没有finalize,那些未标记的对象会被移除吗? - Pacerier

-3

垃圾回收(GC)是一种自动内存管理形式,通过移除不再需要的对象来实现。

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

1- 分配所需的内存空间

2- 进行一些处理

3- 释放该内存空间

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

引用计数垃圾收集:该算法将“对象不再需要”的定义缩减为“没有其他对象引用它”,如果没有引用指向该对象,则将其删除。

标记-清除算法:将每个对象连接到根源。任何未连接到根或其他对象的对象都将被删除。

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


2
我知道什么是垃圾回收,问题是如何控制它何时发生。 - Ed Heal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接