为什么这是JavaScript中的内存泄漏?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了为什么这是JavaScript中的内存泄漏?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4663字,纯文字阅读大概需要7分钟。
内容图文
我正在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>
我了解所有其他泄漏,但这一点脱颖而出.它说DOM和JavaScript对象之间存在循环引用,但我没有看到它.
任何人都可以对此有所了解吗?
编辑:链接似乎已被删除(我甚至刷新了我的页面,它已经关闭).这是Google的缓存(只要持续时间为: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)
解决方法:
对innerFunction onclick的赋值创建了一个函数闭包,它保留了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>
现在,您已经从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>
或者,如果您不需要闭包中的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>
实际上,在泄漏的内存使用量很大的情况下,这只是一个有意义的问题.
>如果您将大量数据存储为DOM属性,则单个对象泄漏可能会泄漏大量数据.这通常是通过不在DOM对象上存储大块数据来解决的.将它们存储在JS中,您可以明确地控制生命周期.
>如果你有一个包含大量javascript交互的长寿命页面,那么创建/销毁DOM对象的操作可以完成很多次.例如,无人看管的幻灯片放映可能会反复创建/销毁DOM对象.即使每件物品的少量内存泄漏最终也会累积并导致问题.在我写的幻灯片中,我只是确保我没有在我添加/删除的这些特定DOM对象上放置任何自定义属性,并且在从DOM中删除对象之前删除了所有事件处理程序.这应该确保不会有循环引用它们.
>你在一个大循环中反复做的任何类型的DOM操作.
内容总结
以上是互联网集市为您收集整理的为什么这是JavaScript中的内存泄漏?全部内容,希望文章能够帮你解决为什么这是JavaScript中的内存泄漏?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。