在IE下的JS编程中,以下的编程方式都会造成即使关闭IE也无法释放内存的问题,下面分类给出: LEhLinux联盟
LEhLinux联盟
1、给DOM对象添加的属性是一个对象的引用。范例: LEhLinux联盟
var MyObject = {}; LEhLinux联盟
document.getElementById('myDiv').myProp = MyObject; LEhLinux联盟
解决方法: LEhLinux联盟
在window.onunload事件中写上: document.getElementById('myDiv').myProp = null; LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
2、DOM对象与JS对象相互引用。范例: LEhLinux联盟
function Encapsulator(element) { LEhLinux联盟
this.elementReference = element; LEhLinux联盟
element.myProp = this; LEhLinux联盟
} LEhLinux联盟
new Encapsulator(document.getElementById('myDiv')); LEhLinux联盟
解决方法: LEhLinux联盟
在onunload事件中写上: document.getElementById('myDiv').myProp = null; LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
3、给DOM对象用attachEvent绑定事件。范例: LEhLinux联盟
function doClick() {} LEhLinux联盟
element.attachEvent("onclick", doClick); LEhLinux联盟
解决方法: LEhLinux联盟
在onunload事件中写上: element.detachEvent('onclick', doClick); LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
4、从外到内执行appendChild。这时即使调用removeChild也无法释放。范例: LEhLinux联盟
var parentDiv = document.createElement("div"); LEhLinux联盟
var childDiv = document.createElement("div"); LEhLinux联盟
document.body.appendChild(parentDiv); LEhLinux联盟
parentDiv.appendChild(childDiv); LEhLinux联盟
解决方法: LEhLinux联盟
从内到外执行appendChild: LEhLinux联盟
var parentDiv = document.createElement("div"); LEhLinux联盟
var childDiv = document.createElement("div"); LEhLinux联盟
parentDiv.appendChild(childDiv); LEhLinux联盟
document.body.appendChild(parentDiv); LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
5、反复重写同一个属性会造成内存大量占用(但关闭IE后内存会被释放)。范例: LEhLinux联盟
for(i = 0; i < 5000; i++) { LEhLinux联盟
hostElement.text = "asdfasdfasdf"; LEhLinux联盟
} LEhLinux联盟
这种方式相当于定义了5000个属性! LEhLinux联盟
解决方法: LEhLinux联盟
其实没什么解决方法:P~~~就是编程的时候尽量避免出现这种情况咯~~ LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
说明: LEhLinux联盟
1、以上资料均来源于微软官方的MSDN站点,链接地址: LEhLinux联盟
http://msdn.microsoft.com/librar ... e_leak_patterns.asp LEhLinux联盟
大家可以到上面这个地址中看到详细的说明,包括范例和图例都有。只是我英文不太好,看不太懂,如果我上述有失误或有需要补充的地方请大家指出。 LEhLinux联盟
LEhLinux联盟
2、对于第一条,事实上包括 element.onclick = funcRef 这种写法也算在其中,因为这也是一个对对象的引用。在页面onunload时应该释放掉。 LEhLinux联盟
LEhLinux联盟
3、对于第三条,在MSDN的英文说明中好像是说即使调用detachEvent也无法释放内存,因为在attachEvent的时候就已经造成内存“LEAK”了,不过detachEvent后情况还是会好一点。不知道是不是这样,请英文好的亲能够指出。 LEhLinux联盟
LEhLinux联盟
4、在实际编程中,这些内存问题的实际影响并不大,尤其是给客户使用时,客户对此绝不会有察觉,然而这些问题对于程序员来说却始终是个心病 --- 有这样的BUG心里总会觉得不舒服吧?能解决则给与解决,这样是最好的。事实上我在webfx.eae.net这样顶级的JS源码站点中,在它们的源码里都会看到采用上述解决方式进行内存的释放管理。 LEhLinux联盟
理解并解决IE的内存泄漏方式 LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
Web开发的发展 LEhLinux联盟
LEhLinux联盟
在过去一些的时候,Web开发人员并没有太多的去关注内存泄露问题。那时的页面间联系大都比较简单,并主要使用不同的连接地址在同一 LEhLinux联盟
LEhLinux联盟
个站点中导航,这样的设计方式是非常有利于浏览器释放资源的。即使Web页面运行中真的出现了资源泄漏,那它的影响也是非常有限而且常常 LEhLinux联盟
LEhLinux联盟
是不会被人在意的。 LEhLinux联盟
LEhLinux联盟
今天人们对Web应用有了高更的要求。一个页面很可能数小时不会发生URL跳转,并同时通过Web服务动态的更新页面内容。复杂的事件关联 LEhLinux联盟
LEhLinux联盟
设计、基于对象的JScript和DHTML技术的广泛采用,使得代码的能力达到了其承受的极限。在这样的情况和改变下,弄清楚内存泄露方式变得 LEhLinux联盟
LEhLinux联盟
非常的急迫,特别是过去这些问题都被传统的页面导航方法给屏蔽了。 LEhLinux联盟
LEhLinux联盟
还算好的事情是,当你明确了希望寻找什么时,内存泄露方式是比较容易被确定的。大多数你能遇到的泄露问题我们都已经知道,你只需 LEhLinux联盟
LEhLinux联盟
要少量额外的工作就会给你带来好处。虽然在一些页面中少量的小泄漏问题仍会发生,但是主要的问题还是很容易解决的。 LEhLinux联盟
LEhLinux联盟
泄露方式 LEhLinux联盟
LEhLinux联盟
在接下来的内容中,我们会讨论内存泄露方式,并为每种方式给出示例。其中一个重要的示例是JScript中的Closure技术,另一个示例是 LEhLinux联盟
LEhLinux联盟
在事件执行中使用Closures。当你熟悉本示例后,你就能找出并修改你已有的大多数内存泄漏问题,但是其它Closure相关的问题可能又会被忽 LEhLinux联盟
LEhLinux联盟
视。 LEhLinux联盟
LEhLinux联盟
现在让我们来看看这些个方式都有什么: LEhLinux联盟
LEhLinux联盟
1、循环引用(Circular References) — IE浏览器的COM组件产生的对象实例和网页脚本引擎产生的对象实例相互引用,就会造成内存泄漏。 LEhLinux联盟
LEhLinux联盟
这也是Web页面中我们遇到的最常见和主要的泄漏方式; LEhLinux联盟
LEhLinux联盟
2、内部函数引用(Closures) — Closures可以看成是目前引起大量问题的循环应用的一种特殊形式。由于依赖指定的关键字和语法结构, LEhLinux联盟
LEhLinux联盟
Closures调用是比较容易被我们发现的; LEhLinux联盟
LEhLinux联盟
3、页面交叉泄漏(Cross-Page Leaks) — 页面交叉泄漏其实是一种较小的泄漏,它通常在你浏览过程中,由于内部对象薄计引起。下面我们 LEhLinux联盟
LEhLinux联盟
会讨论DOM插入顺序的问题,在那个示例中你会发现只需要改动少量的代码,我们就可以避免对象薄计对对象构建带来的影响; LEhLinux联盟
LEhLinux联盟
4、貌似泄漏(Pseudo-Leaks) — 这个不是真正的意义上的泄漏,不过如果你不了解它,你可能会在你的可用内存资源变得越来越少的时候极 LEhLinux联盟
LEhLinux联盟
度郁闷。为了演示这个问题,我们将通过重写Script元素中的内容来引发大量内存的"泄漏"。 LEhLinux联盟
LEhLinux联盟
循环引用 LEhLinux联盟
LEhLinux联盟
循环引用基本上是所有泄漏的始作俑者。通常情况下,脚本引擎通过垃圾收集器(GC)来处理循环引用,但是某些未知因数可能会妨碍从其 LEhLinux联盟
LEhLinux联盟
环境中释放资源。对于IE来说,某些DOM对象实例的状态是脚本无法得知的。下面是它们的基本原则: LEhLinux联盟
LEhLinux联盟
LEhLinux联盟
Figure 1: 基本的循环引用模型LEhLinux联盟
本模型中引起的泄漏问题基于COM的引用计数。脚本引擎对象会维持对DOM对象的引用,并在清理和释放DOM对象指针前等待所有引用的移除 LEhLinux联盟
LEhLinux联盟
。在我们的示例中,我们的脚本引擎对象上有两个引用:脚本引擎作用域和DOM对象的expando属性。当终止脚本引擎时第一个引用会释放,DOM LEhLinux联盟
LEhLinux联盟
对象引用由于在等待脚本擎的释放而并不会被释放。你可能会认为检测并修复假设的这类问题会非常的容易,但事实上这样基本的的示例只是 LEhLinux联盟
LEhLinux联盟
冰山一角。你可能会在30个对象链的末尾发生循环引用,这样的问题排查起来将会是一场噩梦。 LEhLinux联盟
LEhLinux联盟
如果你仍不清楚这种泄漏方式在HTML代码里到底怎样,你可以通过一个全局脚本变量和一个DOM对象来引发并展现它。
<html> LEhLinux联盟
<head> LEhLinux联盟
<script language="JScript"> LEhLinux联盟
var myGlobalObject; LEhLinux联盟
function SetupLeak() LEhLinux联盟
{ LEhLinux联盟
// First set up the script scope to element reference LEhLinux联盟
myGlobalObject = document.getElementById("LeakedDiv"); LEhLinux联盟
LEhLinux联盟
// Next set up the element to script scope reference LEhLinux联盟
document.getElementById("LeakedDiv").expandoProperty = myGlobalObject; LEhLinux联盟
} LEhLinux联盟
LEhLinux联盟
function BreakLeak() LEhLinux联盟
{ LEhLinux联盟
document.getElementById("LeakedDiv").expandoProperty = null; LEhLinux联盟
} LEhLinux联盟
</script> LEhLinux联盟
</head> LEhLinux联盟
<body onload="SetupLeak()" onunload="BreakLeak()"> LEhLinux联盟
<div id="LeakedDiv"></div> LEhLinux联盟
</body> LEhLinux联盟
</html>LEhLinux联盟
Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论