什么是JavaScript垃圾收集?
什么是JavaScript垃圾收集? 为了编写更好的代码,对于Web程序员来说,了解JavaScript垃圾收集有什么重要的意义?
Eric Lippert写了一篇关于这个主题的详细的博客文章 (另外还比较了VBScript )。 更准确地说,他写了关于JScript ,这是微软自己的ECMAScript的实现,虽然非常类似于JavaScript。 我可以想象,你可以认为绝大多数行为对于Internet Explorer的JavaScript引擎是一样的。 当然,从浏览器到浏览器的实现都不尽相同,不过我怀疑你可以采取一些常用的原则并将它们应用到其他浏览器。
引用该页面:
JScript使用非代数标记和清除垃圾收集器。 它是这样工作的:
“范围内”的每个variables都称为“清道夫”。 清道夫可能指的是一个数字,一个对象,一个string,不pipe。 我们维护一个清理者列表 – 当它们超出范围时,variables会在scav列表中移动到scav列表中,并从scav列表中移除。
垃圾收集器不时运行。 首先,它在每个对象,variables,string等等上放置一个“标记” – 所有由GC跟踪的内存。 (JScript在内部使用VARIANT数据结构,在这个结构中有很多额外的未使用的位,所以我们只设置其中一个。)
其次,它清除了清道夫的标记和清道夫参照的传递封闭。 所以如果一个清道夫对象引用一个非清道夫对象,那么我们清除非清道夫的所有内容,以及它所引用的所有内容。 (我使用“闭包”这个词的含义与我以前的文章不同)。
在这一点上,我们知道仍然标记的所有内存都被分配了内存,这是任何范围内variables的任何path无法到达的内存。 所有这些对象被指示撕毁自己,破坏任何循环引用。
垃圾回收的主要目的是让程序员不用担心他们创build和使用的对象的内存pipe理,虽然有时候并没有避免它 – 至less对垃圾回收是如何工作的。
有几点需要注意。 苹果开发者网站有关于这个问题的一些准则 。 两个重要的从那里:
- 使用删除语句。 无论何时使用新语句创build对象,都将其与删除语句配对。 这确保了与该对象相关联的所有内存(包括其属性名称)都可用于垃圾回收。 删除语句在“释放对象”中有更多的讨论。
- 使用var关键字。 任何在不使用var关键字的情况下创build的variables都将在全局范围内创build,并且永远不会有资格进行垃圾回收,从而可能导致内存泄漏。
我想这些实践应该适用于所有JavaScript引擎(在不同的浏览器中),不过因为这是来自苹果的网站,所以它们对于Safari来说可能有点特定。 (也许有人可以澄清?)
希望有所帮助。
当涉及到DOM对象时,要小心循环引用:
JavaScript中的内存泄漏模式
请记住,只有在没有对象的活动引用时才能回收内存。 这是闭包和事件处理程序常见的陷阱,因为一些JS引擎不会检查哪些variables实际上在内部函数中被引用,而只是保留封闭函数的所有局部variables。
这是一个简单的例子:
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
不适用于局部variables和函数参数: delete
从属性中删除属性,variables对象不可访问 – ES5严格模式甚至会抛出一个ReferenceError
如果你试图删除一个局部variables!)。
如果您关心内存消耗,我build议尽可能避免不必要的closures。
就我所知,JavaScript的对象是在对象没有引用的情况下被周期性地垃圾收集的。 这是自动发生的事情,但是如果你想了解更多关于它是如何工作的,在C ++级别,看看WebKit或V8源代码是有意义的
通常情况下,你不需要考虑这个问题,但是,在IE5.5和IE6的早期版本等旧版浏览器中,当前版本的闭包会创build一个循环引用,当未选中时会导致内存耗尽。 在特定情况下,我的意思是闭包,就是当您将一个JavaScript引用添加到一个dom对象,并将一个对象引用回JavaScript对象的DOM对象。 基本上它永远不会被收集,并最终会导致操作系统变得不稳定的testing应用程序,循环创build崩溃。 在实践中,这些泄漏通常很小,但为了保持代码清洁,应该删除对DOM对象的JavaScript引用。
通常最好使用delete关键字来立即解除引用的JSON数据等大对象,并根据需要对其进行处理,特别是在移动Web开发中。 这导致GC的下一次扫描删除该对象并释放其内存。
来自博客的好话
与JScript组件一样,DOM组件也是“垃圾收集”,这意味着如果您在任一组件中创build对象,然后失去该对象的跟踪,它最终将被清除。
例如:
function makeABigObject() { var bigArray = new Array(20000); }
当您调用该函数时,JScript组件会创build一个可在该函数内访问的对象(名为bigArray)。 但是,函数一返回,你就“失去了”bigArray的踪迹,因为没有办法再引用它了。 那么,JScript组件意识到你已经失去了它的踪迹,所以bigArray被清理 – 它的内存被回收。 DOM组件中的相同的东西。 如果你说document.createElement('div')
或类似的东西,那么DOM组件为你创build一个对象。 一旦你以某种方式失去了对象的轨迹,DOM组件将清理相关的东西。
垃圾收集(GC)是一种通过移除不再需要的对象来自动进行内存pipe理的forms。
处理内存的任何进程都遵循以下步骤:
1 – 分配你需要的内存空间
2 – 做一些处理
3 – 释放这个内存空间
有两种主要algorithm用于检测不再需要哪些对象。
引用计数垃圾回收 :该algorithm将“不再需要对象”的定义降低为“没有其他对象引用对象”的定义,如果没有引用对象,则该对象将被删除
标记和扫描algorithm :将每个对象连接到根源。 任何对象都不会连接到根或其他对象。 这个对象将被删除。
目前最现代的浏览器使用第二种algorithm。
“在计算机科学中,垃圾回收(GC)是自动内存pipe理的一种forms,垃圾回收器或垃圾收集器试图回收应用程序永远不会访问或突变的对象所使用的垃圾或内存。
所有的JavaScript引擎都有自己的垃圾收集器,它们可能有所不同。 大多数时候你不必处理他们,因为他们只是做他们应该做的事情。
编写更好的代码主要取决于您对编程原理,语言和特定实现的了解程度。
什么是JavaScript垃圾收集?
检查这个
为了编写更好的代码,对于Web程序员来说,了解JavaScript垃圾收集有什么重要意义?
在Javascript中,你不关心内存分配和释放。 整个问题都要求给Javascript解释器。 在Javascript中仍然有可能泄漏,但是他们是解释器的错误。 如果您对这个主题感兴趣,您可以在www.memorymanagement.org上阅读更多内容
在Windows上,您可以使用Drip.exe来查找内存泄漏,或检查您的空闲内存例程是否工作。
这很简单,只需input一个网站的URL,你会看到集成的IE渲染器的内存消耗。 然后点击刷新,如果内存增加,你发现网页上的某处存在内存泄漏。 但是,这也是非常有用的,看看是否为IE释放内存的例程。