Ada*_*dam 5 javascript memory-leaks memory-management
我正在IBM的网站上阅读这篇文章(http://www.ibm.com/developerworks/web/library/wa-memleak/)关于JavaScript中的内存泄漏,当我遇到一个看起来不太喜欢它的内存泄漏时泄露:
<html>
<body>
<script type="text/javascript">
document.write("Program to illustrate memory leak via closure");
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction(){
alert("Hi! I will leak");
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
// This is used to make the leak significant
};
</script>
<button id="element">Click Me</button>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
我了解所有其他泄漏,但这一点脱颖而出.它说DOM和JavaScript对象之间存在循环引用,但我没有看到它.
任何人都可以对此有所了解吗?
编辑:链接似乎已被删除(我甚至刷新了我的页面,它已经关闭).这是谷歌的缓存(只要持续时间:http://webcache.googleusercontent.com/search?q = cache:kLR-FJUeKv0J:www.ibm.com/developerworks/web/library/wa-memleak/+memory+ management + in + javascript&cd = 1&hl = en&ct = clnk&gl = us&client = firefox-a)
分配到onclick的innerFunction创建功能关闭,保留了在范围变量的值innerFunction.这允许代码innerFunction引用它上面的变量,并且是javascript的理想特性(某些其他语言没有的东西).
那些innerFunction包含范围的变量obj.因此,只要存在对此闭包的引用,就会保留该闭包中的变量.它是一次性内存使用,因此它不会随着时间的推移而累积,因此通常不会很重要.但是,如果你将大数据放入其中一个变量中,然后预期它将被释放,那么"是"你会使用比预期更多的浏览器内存.
在这个特定的例子中,这可能导致问题,你在JS <==> DOM之间有一个循环引用.在JS中,您保留了(在函数闭包中)对obj变量中DOM对象的引用.在DOM对象中,您保留了对JS代码和函数闭包的引用以及对onclick属性的赋值.一些较旧的浏览器非常愚蠢,即使你从DOM中删除"元素"对象,循环引用也会使垃圾收集器不再释放内存.这在现代浏览器中不是问题,因为它们足够智能以查看此循环引用,并且如果没有外部引用它仍然可以释放该对象.
在您的特定代码中,您实际上并未创建泄漏,因为该元素仍在DOM中.bigString只是你附加到DOM元素的一大块数据,它将保留在那里直到你删除该属性或删除DOM对象.这不是泄漏,只是存储.
如果你这样做,这将成为IE6泄漏的唯一方法:
<html>
<body>
<script type="text/javascript">
document.write("Program to illustrate memory leak via closure");
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction(){
alert("Hi! I will leak");
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
// This is used to make the leak significant
};
// called later in your code
function freeObject() {
var obj = document.getElementById("element");
obj.parentNode.removeChild(obj); // remove object from DOM
}
</script>
<button id="element">Click Me</button>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
现在,您已经从DOM中移除了对象(稍后在代码中)并且可能期望释放与其关联的所有内存,但循环引用使得在IE6中不会发生这种情况.您可以通过执行以下操作来解决此问题:
<html>
<body>
<script type="text/javascript">
document.write("Program to illustrate memory leak via closure");
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction(){
alert("Hi! I will leak");
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
// This is used to make the leak significant
};
// called later in your code
function freeObject() {
var obj = document.getElementById("element");
obj.onclick=null; // clear handler and closure reference
obj.parentNode.removeChild(obj); // remove object from DOM
}
</script>
<button id="element">Click Me</button>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
或者,如果您不需要obj闭包中的引用,则可以使用以下内容完全取消闭包中的引用:
<html>
<body>
<script type="text/javascript">
document.write("Program to illustrate memory leak via closure");
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction(){
alert("Hi! I will leak");
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
// This is used to make the leak significant
obj = null; // kills the circular reference, obj will be null if you access if from innerFunction()
};
</script>
<button id="element">Click Me</button>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
实际上,在泄漏的内存使用量很大的情况下,这只是一个有意义的问题.
| 归档时间: |
|
| 查看次数: |
1121 次 |
| 最近记录: |