IE的内存泄漏问题
The Internet Explorer Memory Leak Problem
The Internet Explorer web browser (verified on versions 4 to 6 (6 is current at the time of writing)) has a fault in its garbage collection system that prevents it from garbage collecting ECMAScript and some host objects if those host objects form part of a "circular" reference. The host objects in question are any DOM Nodes (including the document object and its descendants) and ActiveX objects. If a circular reference is formed including one or more of them, then none of the objects involved will be freed until the browser is closed down, and the memory that they consume will be unavailable to the system until that happens.
IE浏览器从版本4到6的GC系统有个错误,导致对ECMAScript及一些形成“循环引用”的host对象的GC失败。
host对象即DOM中的节点(包括document对象及其所有层次结构中的节点)以及ActiveX对象.
如果一个引用环中包括他们中的任何一个或多个,那么当浏览器关闭以后,他们一个都不会被释放,而他们所消耗的内存就泄漏咯。
A circular reference is when two or more objects refer to each other in a way that can be followed and lead back to the starting point. Such as object 1 has a property that refers to object 2, object 2 has a property that refers to object 3 and object 3 has a property that refers back to object 1. With pure ECMAScript objects as soon as no other objects refer to any of objects 1, 2 or 3 the fact that they only refer to each other is recognised and they are made available for garbage collection. But on Internet Explorer, if any of those objects happen to be a DOM Node or ActiveX object, the garbage collection cannot see that the circular relationship between them is isolated from the rest of the system and free them. Instead they all stay in memory until the browser is closed.
一个循环引用就是两个或多个对象互相引用并回到一个出发点。比如 object 1有个属性是引用 object 2,object 2也有个属性引用object 3, object3 则引用了object 1。对于纯粹的ECMAScript对象来说,一旦没有其他对象指向对象1,2或3之中的任何一个的时候,1、2、3只是互相指向的这个事实就被辨认出来了,垃圾收集就开始起作用了。但在IE中,如果这些对象是DOM节点或者Activex对象的话,GC无法发现他们之间的循环关系已经从系统中隔离出来,因此无法释放之,他们被遗留在内存中直至浏览器被关闭。
Closures are extremely good at forming circular references. If a function object that forms a closure is assigned as, for example, and event handler on a DOM Node, and a reference to that Node is assigned to one of the Activation/Variable objects in its scope chain then a circular reference exists. DOM_Node.onevent -> function_object.[[scope]] -> scope_chain -> Activation_object.nodeRef -> DOM_Node. It is very easy to do, and a bit of browsing around a site that forms such a reference in a piece of code common to each page can
consume most of the systems memory (possibly all).
关闭动作最容易形成循环引用。如果一个产生关闭动作的函数对象被赋值为:比如说,一个DOM节点上的事件句柄,并且这个节点的一个引用被赋给其作用域中的一个变量,循环引用关系就出现了。 DOM_Node.onevent -> function_object.[[scope]] -> scope_chain -> Activation_object.nodeRef -> DOM_Node. 很容易发生这样的事情,稍微浏览一下这种站点,即其中每个页面都有某段通用代码,而这种代码形成类似这样的引用的话,系统内存就耗得飞快了。
Care can be taken to avoid forming circular references and remedial action can be taken when they cannot otherwise be avoided, such as using IE's onunload event to null event handling function references. Recognising the problem and understanding closures (and their mechanism) is the key to avoiding this problem with IE.