本文翻译自:What is JavaScript garbage collection?
What is JavaScript garbage collection? 什么是JavaScript垃圾回收? What's important for a web programmer to understand about JavaScript garbage collection, in order to write better code? 为了编写更好的代码,对于Web程序员来说,了解JavaScript垃圾回收有什么重要意义?
#1楼
参考:https://stackoom.com/question/3cto/什么是JavaScript垃圾回收
#2楼
garbage collection (GC) is a form of automatic memory management by removing the objects that no needed anymore. 垃圾回收(GC)是一种自动内存管理形式,它可以删除不再需要的对象。
any process deal with memory follow these steps: 任何处理内存的过程,请按照以下步骤操作:
1 - allocate your memory space you need 1-分配所需的内存空间
2 - do some processing 2-做一些处理
3 - free this memory space 3-释放此内存空间
there are two main algorithm used to detect which objects no needed anymore. 有两种主要算法可用来检测不再需要哪些对象。
Reference-counting garbage collection : this algorithm reduces the definition of "an object is not needed anymore" to "an object has no other object referencing to it", the object will removed if no reference point to it 引用计数垃圾回收 :此算法将“不再需要某个对象”的定义简化为“某个对象没有其他引用它的对象”,如果没有引用指向该对象,则该对象将被删除
Mark-and-sweep algorithm : connect each objects to root source. 标记扫描算法 :将每个对象连接到根源。 any object doesn't connect to root or other object. 任何对象都不会连接到根或其他对象。 this object will be removed. 该对象将被删除。
currently most modern browsers using the second algorithm. 当前大多数现代浏览器都使用第二种算法。
#3楼
Reference types do not store the object directly into the variable to which it is assigned, so the object variable in this example doesn't actually contain the object instance. 引用类型不会将对象直接存储到为其分配了变量的变量中,因此本示例中的对象变量实际上并不包含对象实例。 Instead, it holds a pointer (or reference) to the location in memory where the object exists 相反,它持有指向内存中对象所在位置的指针(或引用)
var object = new Object();
if you assign one variable to another, each variable gets a copy of the pointer, and both still reference the same object in memory. 如果将一个变量分配给另一个变量,则每个变量都将获得指针的副本,并且两个变量仍引用内存中的同一对象。
var object1 = new Object();
var object2 = object1;
JavaScript is a garbage-collected language, so you don't really need to worry about memory allocations when you use reference types. JavaScript是一种垃圾回收语言,因此使用引用类型时,您实际上不必担心内存分配。 However, it's best to dereference objects that you no longer need so that the garbage collector can free up that memory. 但是,最好取消引用不再需要的对象,以便垃圾回收器可以释放该内存。 The best way to do this is to set the object variable to null. 最好的方法是将对象变量设置为null。
var object1 = new Object();
// do something
object1 = null; // dereference
Dereferencing objects is especially important in very large applications that use millions of objects. 在使用数百万个对象的超大型应用程序中, 取消引用对象尤为重要。
from The Principles of Object-Oriented JavaScript - NICHOLAS C. ZAKAS 面向对象的JavaScript原理的介绍-NICHOLAS C. ZAKAS
#4楼
What is JavaScript garbage collection? 什么是JavaScript垃圾回收?
What's important for a web programmer to understand about JavaScript garbage collection, in order to write better code? 为了编写更好的代码,对于Web程序员来说,了解JavaScript垃圾回收有什么重要意义?
In Javascript you don't care about memory allocation and deallocation. 在Javascript中,您无需关心内存分配和释放。 The whole problem is demanded to the Javascript interpreter. 整个问题都需要Javascript解释器来解决。 Leaks are still possible in Javascript, but they are bugs of the interpreter. 在Javascript中仍然可能发生泄漏,但是它们是解释器的错误。 If you are interested in this topic you could read more in www.memorymanagement.org 如果您对此主题感兴趣,可以在www.memorymanagement.org上阅读更多内容。
#5楼
Eric Lippert wrote a detailed blog post about this subject a while back (additionally comparing it to VBScript ). 埃里克·利珀特(Eric Lippert)不久前就此主题撰写了一篇详细的博客文章 (另外将其与VBScript进行了比较)。 More accurately, he wrote about JScript , which is Microsoft's own implementation of ECMAScript, although very similar to JavaScript. 更准确地说,他写了有关JScript的信息,尽管它非常类似于JavaScript,但它是Microsoft自己的ECMAScript实现。 I would imagine that you can assume the vast majority of behaviour would be the same for the JavaScript engine of Internet Explorer. 我可以想象,您可以假设绝大多数行为对于Internet Explorer的JavaScript引擎都是相同的。 Of course, the implementation will vary from browser to browser, though I suspect you could take a number of the common principles and apply them to other browsers. 当然,不同浏览器的实现方式会有所不同,尽管我怀疑您可以采用一些通用原则并将其应用于其他浏览器。
Quoted from that page: 从该页面引用:
JScript uses a nongenerational mark-and-sweep garbage collector. JScript使用了非世代的标记清除垃圾收集器。 It works like this: 它是这样的:
Every variable which is "in scope" is called a "scavenger". 每个“范围内”的变量都称为“清除剂”。 A scavenger may refer to a number, an object, a string, whatever. 清道夫可以指数字,对象,字符串等。 We maintain a list of scavengers -- variables are moved on to the scav list when they come into scope and off the scav list when they go out of scope. 我们维护了一个清除剂列表-变量在进入作用域时将移至scav列表中,而当变量超出作用域时将其移至scav列表中。
Every now and then the garbage collector runs. 垃圾收集器不时地运行。 First it puts a "mark" on every object, variable, string, etc – all the memory tracked by the GC. 首先,它在每个对象,变量,字符串等(GC跟踪的所有内存)上都打上“标记”。 (JScript uses the VARIANT data structure internally and there are plenty of extra unused bits in that structure, so we just set one of them.) (JScript在内部使用VARIANT数据结构,并且该结构中有许多额外的未使用位,因此我们仅设置其中之一。)
Second, it clears the mark on the scavengers and the transitive closure of scavenger references. 其次,它清除了清除剂上的标记以及清除剂引用的可传递性关闭。 So if a scavenger object references a nonscavenger object then we clear the bits on the nonscavenger, and on everything that it refers to. 因此,如果清除剂对象引用了非清除剂对象,则我们清除非清除剂及其所引用的所有内容上的位。 (I am using the word "closure" in a different sense than in my earlier post.) (我使用“ closure”一词的含义与我以前的帖子不同。)
At this point we know that all the memory still marked is allocated memory which cannot be reached by any path from any in-scope variable. 至此,我们知道所有仍标记为已分配内存的内存无法通过任何范围内变量的任何路径访问。 All of those objects are instructed to tear themselves down, which destroys any circular references. 指示所有这些对象将其自身拆除,这会破坏任何循环引用。
The main purpose of garbage collection is to allow the programmer not to worry about memory management of the objects they create and use, though of course there's no avoiding it sometimes - it is always beneficial to have at least a rough idea of how garbage collection works. 垃圾回收的主要目的是使程序员不必担心他们创建和使用的对象的内存管理,尽管当然有时并不能避免这种情况-至少对垃圾回收的工作原理有个大概的了解总是有益的。
There are a few particular points of which to be aware. 有一些特别的要注意的地方。 The Apple developer site has some guidelines on the matter. Apple开发人员网站对此有一些指导原则 。 Two important ones from there: 从那里两个重要的:
- Use delete statements. 使用删除语句。 Whenever you create an object using a new statement, pair it with a delete statement. 每当使用新语句创建对象时,都将其与delete语句配对。 This ensures that all of the memory associated with the object, including its property name, is available for garbage collection. 这样可以确保与对象关联的所有内存(包括其属性名称)都可用于垃圾回收。 The delete statement is discussed more in “Freeing Objects.” 在“释放对象”中将详细讨论delete语句。
- Use the var keyword. 使用var关键字。 Any variable created without the var keyword is created at the global scope and is never eligible for garbage collection, presenting the opportunity for a memory leak. 任何不带var关键字创建的变量都将在全局范围内创建,并且永远不会进行垃圾回收,这会导致内存泄漏。
I would imagine that the practices should apply to all JavaScript engines (in different browsers), though because this is from an Apple site, they may be somewhat specific to Safari. 我想这些做法应该适用于所有JavaScript引擎(在不同的浏览器中),尽管由于它来自Apple网站,所以它们可能特定于Safari。 (Perhaps someone could clarify that?) (也许有人可以澄清吗?)
Hope that helps. 希望能有所帮助。
#6楼
Beware of circular references when DOM objects are involved: 当涉及DOM对象时,请注意循环引用:
Memory leak patterns in JavaScript JavaScript中的内存泄漏模式
Keep in mind that memory can only be reclaimed when there are no active references to the object. 请记住,只有在没有有效引用该对象的情况下,才可以回收内存。 This is a common pitfall with closures and event handlers, as some JS engines will not check which variables actually are referenced in inner functions and just keep all local variables of the enclosing functions. 这是闭包和事件处理程序的常见陷阱,因为某些JS引擎不会检查内部函数中实际引用了哪些变量,而仅保留封闭函数的所有局部变量。
Here's a simple example: 这是一个简单的例子:
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!
};
}
A naive JS implementation can't collect bigString
as long as the event handler is around. 只要事件处理程序存在,幼稚的JS实现就无法收集bigString
。 There are several ways to solve this problem, eg setting bigString = null
at the end of init()
( delete
won't work for local variables and function arguments: delete
removes properties from objects, and the variable object is inaccessible - ES5 in strict mode will even throw a ReferenceError
if you try to delete a local variable!). 有几种方法来解决这个问题,例如,设置bigString = null
在年底init()
delete
将不能为局部变量和函数参数的工作: delete
从对象中删除属性,变量对象是不可访问- ES5严格如果您尝试删除局部变量,则该模式甚至会抛出ReferenceError
!)。
I recommend to avoid unnecessary closures as much as possible if you care for memory consumption. 如果您关心内存消耗,我建议尽可能避免不必要的关闭。