javascript内存泄露
来源:互联网 发布:windows develop 编辑:程序博客网 时间:2024/05/29 10:23
原文: http://www.pc6.com/infoview/Article_48896.html
以下是常见的几种javascript内存泄露的情况:
一、循环引用:
- <html>
- <head>
- < script language ="JScript">
- var myGlobalObject;
- function SetupLeak() // 产生循环引用,因此会造成内存泄露
- {
- // First set up the script scope to element reference
- myGlobalObject = document.getElementById("LeakedDiv");
- // Next set up the element to script scope reference
- document.getElementById("LeakedDiv").expandoProperty = myGlobalObject;
- }
- </head>
- <body onload = "SetupLeak()">
- <div id ="LeakedDiv" ></div>
- </body>
- </html>
我们可以看到,myGlobalObject指向了一个DOM对象,而这个DOM对象的一个属性又指向了myGlobalObject,循环引用出现,内存泄露,其原理如下:
解决方案很简单,在确保属性不再使用后,加入以下代码就可以了:
- function BreakLeak(){ // 解开循环引用,解决内存泄露问题
- document.getElementById( " LeakedDiv " ).expandoProperty = null ;
- }
说起来容易,不过当我们程序非常复杂的时候,发现和修改就没有这么容易了.
二、闭包(Closures)
仍然先看一段代码:
- <html>
- <head>
- <script language="JScript">
- function AttachEvents(element)
- {
- // This structure causes element to ref ClickEventHandler
- element.attachEvent( " onclick " , ClickEventHandler); function ClickEventHandler()
- {
- // This closure refs element
- }
- } function SetupLeak()
- {
- // The leak happens all at once
- AttachEvents(document.getElementById( " LeakedDiv " ));
- }
- </script>
- </head> <body onload="SetupLeak()">
- <div id="LeakedDiv"></div>
- </body>
- </html>
闭包的一个内部方法赋给了element对象,产生了一个作用域的循环引用,从而造成内存泄露.其原理图如下:
解决方案如下,在确定事件不再使用后,解除事件的绑定:
- function BreakLeak() {
- document.getElementById(”LeakedDiv”).detachEvent(”onclick”, document.getElementById(”LeakedDiv”).expandoClick);
- document.getElementById(”LeakedDiv”).expandoClick = null;
- }
通常情况下,常用的js框架都帮我们解决了这个问题,不需要我们自己处理,这也是使用框架的一个好处.
三、Cross-Page-Leaks
仍然先看一个例子:
- <html>
- <head>
- <script language="JScript">
- function LeakMemory()
- {
- var hostElement = document.getElementById("hostElement"); // Do it a lot, look at Task Manager for memory response
- for (i = 0 ; i < 5000 ; i ++ )
- {
- var parentDiv =
- document.createElement("<div onClick='foo()'>");
- var childDiv =
- document.createElement("<div onClick='foo()'>"); // This will leak a temporary object
- parentDiv.appendChild(childDiv);
- hostElement.appendChild(parentDiv);
- hostElement.removeChild(parentDiv);
- parentDiv.removeChild(childDiv);
- parentDiv = null ;
- childDiv = null ;
- }
- hostElement = null ;
- } function CleanMemory()
- {
- var hostElement = document.getElementById("hostElement"); // Do it a lot, look at Task Manager for memory response
- for (i = 0 ; i < 5000 ; i ++ )
- {
- var parentDiv = document.createElement("<div onClick='foo()'>");
- var childDiv = document.createElement("<div onClick='foo()'>"); // Changing the order is important, this won’t leak
- hostElement.appendChild(parentDiv);
- parentDiv.appendChild(childDiv);
- hostElement.removeChild(parentDiv);
- parentDiv.removeChild(childDiv);
- parentDiv = null ;
- childDiv = null ;
- }
- hostElement = null ;
- }
- </div></div></script>
- </head>
- <body>
- <button onclick ="LeakMemory()"> Memory Leaking Insert </button>
- <button onclick ="CleanMemory()"> Clean Insert </button>
- <div id ="hostElement"></div>
- </body>
- </html>
LeakMemory和CleanMemory这两段函数的唯一区别就在于他们的代码的循序,从代码上看,两段代码的逻辑都没有错.
但LeakMemory却会造成泄露.原因是LeakMemory()会先建立起parentDiv和childDiv之间的连接,这时候,为了让 childDiv能够获知parentDiv的信息,因此IE需要先建立一个临时的scope对象.而后parentDiv建立了和 hostElement对象的联系,parentDiv和childDiv直接使用页面document的scope.可惜的是,IE不会释放刚才那个临时的scope对象的内存空间,直到我们跳转页面,这块空间才能被释放.而CleanMemory函数不同,他先把parentDiv和 hostElement建立联系,而后再把childDiv和parentDiv建立联系,这个过程不需要单独建立临时的scope,只要直接使用页面 document的scope就可以了, 所以也就不会造成内存泄露了.但是,需要特别说明一下,如果LeakMemory方法里面,创建的div对象上不绑定script事件,那么也不会有泄漏,这个可以理解为ie的bug,大家记住就可以了,不需要过分深究.其原理如下:
四、Pseudo-Leaks:
同样可以理解为ie的bug的一种泄露:
- <html>
- <head>
- <script language="JScript">
- function LeakMemory()
- {
- // Do it a lot, look at Task Manager for memory response
- for(i = 0; i < 5000; i++)
- {
- hostElement.text = “function foo() { }”;
- }
- }
- </script>
- </script></head>
- <body>
- <button onclick=”LeakMemory()”>Memory Leaking Insert</button>
- <script id=”hostElement”>function foo() { }</script>
- </body>
- </html>
没什么特别的好解释,记住就可以了.
关于这四种泄漏的具体描述,还是请各位参照原文:http://msdn.microsoft.com/en-us/library/Bb250448
以上是几种主要的泄露,当然,除此之外,网上还有一些其他的讨论,比如var str = "lalala";alert(str.length);这个简单的语句也会造成内存泄露,原因是类型转换的时候,ie生成了一个临时对象,这个临时对象被泄漏了.类似情况还有很多,大家有兴趣可以自己去搜集整理.
最后说一下,只要ie6还健在,作为前端开发人员,就不能逃避这些问题,当然,也不必过分深究,比如闭包的情况就比较难避免,就像我一开始说的,毕竟,javascript造成的内存泄露不是程序和项目的瓶颈,我们需要在各方面进行权衡.
- 关于javascript内存泄露
- javascript 内存泄露
- Javascript内存泄露
- javascript 中的内存泄露
- JavaScript 内存泄露
- javascript内存泄露
- javascript内存泄露
- javascript内存泄露
- JavaScript内存泄露
- JavaScript—内存泄露
- JavaScript 中的内存泄露模式
- JavaScript 中的内存泄露模式
- JavaScript 中的内存泄露模式
- javascript 内存泄露工具使用
- javascript 内存泄露工具使用
- javascript 内存泄露工具使用
- javascript 内存泄露工具使用
- javascript 内存泄露工具使用
- 关于MVC4.0 WebAPI上传图片重命名以及图文结合
- OpenCV坐标体系的初步认识
- Android Adapter回调接口
- Intent 详解(转)
- IDL/C 二进制数据的读取和写入
- javascript内存泄露
- OpenGL编程逐步深入(四)Shaders
- 网络术语MSL/TTL/RTT
- 成功云企业遵循的十项最佳实践
- java执行JavaScript脚本
- c++多线程编程
- 表单校验
- java中\r与\n的区别 (主要是在windows中DOS命令下)
- 质量保证和质量控制的区别