什么是JavaScript垃圾收集?

什么是JavaScript垃圾收集? 为了编写更好的代码,对于Web程序员来说,了解JavaScript垃圾收集有什么重要意义?


Eric Lippert写了一篇关于此主题的详细博客文章 (另外还将其与VBScript比较)。 更准确地说,他写了关于JScript的文章,这是微软自己实现的ECMAScript,尽管与JavaScript很相似。 我想你可以认为绝大多数的行为对于Internet Explorer的JavaScript引擎是一样的。 当然,从浏览器到浏览器的实现会有所不同,但我怀疑你可以采取一些常用的原则并将它们应用到其他浏览器。

引用该页面:

JScript使用非代数标记和扫描垃圾收集器。 它是这样工作的:

  • “范围内”的每个变量都称为“清道夫”。 清道夫可能指的是数字,对象,字符串等。 我们维护一个清理者列表 - 当它们超出范围时,变量会在scav列表中移入scav列表并从scav列表中移出。

  • 垃圾收集器不时运行。 首先,它在每个对象,变量,字符串等上放置一个“标记” - 所有由GC跟踪的内存。 (JScript在内部使用VARIANT数据结构,并且在该结构中有很多额外的未使用位,所以我们只设置其中一个。)

  • 其次,它清除了清道夫的标记和清道夫参考的传递封闭。 所以如果一个清道夫对象引用了一个非清道夫对象,那么我们就清除非清道夫和它所引用的所有内容。 (我使用的是“封闭”这个词,与我之前的文章不同)。

  • 此时我们知道仍然标记的所有内存都被分配了内存,这是无法通过任何范围内变量的任何路径到达的内存。 所有这些物体都被指示将自己撕下来,这会破坏任何循环引用。

  • 垃圾回收的主要目的是让程序员不用担心他们创建和使用的对象的内存管理,尽管有时候并没有避免这种情况 - 至少对垃圾收集的工作方式至少有一个大概的想法总是有益的。

    有几点需要注意。 苹果开发者网站有关于这个问题的一些指导 。 两个重要的从那里:

  • 使用删除语句。 无论何时使用新语句创建对象,都要使用删除语句进行配对。 这可确保与对象关联的所有内存(包括其属性名称)都可用于垃圾回收。 删除语句在“释放对象”中有更多的讨论。
  • 使用var关键字。 任何在不使用var关键字的情况下创建的变量都会在全局范围内创建,并且永远不会有资格进行垃圾回收,从而导致内存泄漏。
  • 我认为这些实践应该适用于所有JavaScript引擎(在不同的浏览器中),尽管这些引擎来自Apple网站,但它们可能对Safari有一定的特殊性。 (也许有人可以澄清这一点?)

    希望有所帮助。


    当涉及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 = nulldelete不适用于局部变量和函数参数: delete从对象中删除属性,并且变量对象不可访问 - ES5严格模式甚至会尝试删除局部变量时抛出ReferenceError !)。

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


    就我所知,JavaScript的对象是在没有引用保留给对象的情况下定期进行垃圾收集的。 这是自动发生的事情,但如果你想了解更多关于它的工作方式,在C ++级别,查看WebKit或V8源代码是很有意义的

    通常情况下,您不需要考虑它,但是,在较旧的浏览器(如IE 5.5和早期版本的IE 6)中,以及可能的当前版本中,闭包会创建循环引用,如果未选中则最终会占用内存。 在特定情况下,我的意思是关于闭包,就是当你将一个JavaScript引用添加到一个dom对象,并将一个对象添加到一个返回JavaScript对象的DOM对象。 基本上它不可能被收集,并且最终会导致操作系统在测试应用程序中变得不稳定,这些测试应用程序会导致崩溃。 在实践中,这些泄漏通常很小,但为了保持代码清洁,应该删除对DOM对象的JavaScript引用。

    通常,最好使用delete关键字来立即取消引用已收到的JSON数据等大对象,并根据需要执行任何操作,尤其是在移动Web开发中。 这会导致GC的下一次扫描移除该对象并释放其内存。

    链接地址: http://www.djcxy.com/p/701.html

    上一篇: What is JavaScript garbage collection?

    下一篇: How to determine whether an object has a given property in JavaScript