关于Javascript的内存泄漏问题的整理稿

写了好长时间javascript小功能模块,从来没有关注过内存泄漏问题。记得以前写C++程序的时候,内存泄漏是个严重的问题,我想是时候关注一下了。网上找了篇文章,Mark一下。原文地址:http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html

常规循环引用内存泄漏和Closure内存泄漏

要了解javascript的内存泄漏问题,首先要了解的就是javascript的GC原理。

我记得原来在犀牛书《JavaScript: The Definitive Guide》中看到过,IE使用的GC算法是计数器,因此只碰到循环 引用就会造成memory leakage。后来一直觉得和观察到的现象很不一致,直到看到Eric的文章,才明白犀牛书的说法没有说得很明确,估计该书成文后IE升级过算法吧。 在IE 6中,对于javascript object内部,jscript使用的是mark-and-sweep算法,而对于javascript object与外部object(包括native object和vbscript object等等)的引用时,IE 6使用的才是计数器的算法。

Eric Lippert在http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx一文中提到IE 6中JScript的GC算法使用的是nongeneration mark-and-sweep。对于javascript对算法的实现缺陷,文章如是说: 
"The benefits of this approach are numerous, but the principle benefit is that circular references are not leaked unless the circular reference involves an object not owned by JScript. " 
也就是说,IE 6对于纯粹的Script Objects间的Circular References是可以正确处理的,可惜它处理不了的是JScript与Native Object(例如Dom、ActiveX Object)之间的Circular References。 
所以,当我们出现Native对象(例如Dom、ActiveX Object)与Javascript对象间的循环引用时,内存泄露的问题就出现了。当然,这个bug在IE 7中已经被修复了[http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html]。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp 中有个示意图和简单的例子体现了这个问题:

Html代码  

  1. < html >
  2. < head >
  3. < script language = " JScript " >
  4. var  myGlobalObject;
  5. function  SetupLeak()  // 产生循环引用,因此会造成内存泄露
  6. {
  7. //  First set up the script scope to element reference
  8. myGlobalObject  =
  9. document.getElementById( " LeakedDiv " );
  10. //  Next set up the element to script scope reference
  11. document.getElementById( " LeakedDiv " ).expandoProperty  =
  12. myGlobalObject;
  13. }
  14. function  BreakLeak()  // 解开循环引用,解决内存泄露问题
  15. {
  16. document.getElementById( " LeakedDiv " ).expandoProperty  =
  17. null ;
  18. }
  19. </ script >
  20. </ head >
  21. < body onload = " SetupLeak() "  onunload = " BreakLeak() " >
  22. < div id = " LeakedDiv " ></ div >
  23. </ body >
  24. </ html >

上面这个例子,看似很简单就能够解决内存泄露的问题。可惜的是,当我们的代码中的结构复杂了以后,造成循环引用的原因开始变得多样,我们就没法那么容易观察到了,这时候,我们必须对代码进行仔细的检查。 
尤其是当碰到Closure,当我们往Native对象(例如Dom对象、ActiveX Object)上绑定事件响应代码时,一个不小心,我们就会制造出Closure Memory Leak。其关键原因,其实和前者是一样的,也是一个跨javascript object和native object的循环引用。只是代码更为隐蔽,这个隐蔽性,是由于javascript的语言特性造成的。但在使用类似内嵌函数的时候,内嵌的函数有拥有一 个reference指向外部函数的scope,包括外部函数的参数,因此也就很容易造成一个很隐蔽的循环引用,例如: 
DOM_Node.onevent ->function_object.[ [ scope ] ] ->scope_chain ->Activation_object.nodeRef ->DOM_Node。

[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp]有个例子极深刻地显示了该隐蔽性:

Html代码  

  1. < html >
  2. < head >
  3. < script language = " JScript " >
  4. function  AttachEvents(element)
  5. {
  6. //  This structure causes element to ref ClickEventHandler  //element有个引用指向函数ClickEventHandler()
  7. element.attachEvent( " onclick " , ClickEventHandler);
  8. function  ClickEventHandler()
  9. {
  10. //  This closure refs element  //该函数有个引用指向AttachEvents(element)调用Scope,也就是执行了参数element。
  11. }
  12. }
  13. function  SetupLeak()
  14. {
  15. //  The leak happens all at once
  16. AttachEvents(document.getElementById( " LeakedDiv " ));
  17. }
  18. </ script >
  19. </ head >
  20. < body onload = " SetupLeak() "  onunload = " BreakLeak() " >
  21. < div id = " LeakedDiv " ></ div >
  22. </ body >
  23. </ html >

还有这个例子在IE 6中同样原因会引起泄露

Html代码  

  1. function  leakmaybe() {
  2. var  elm  =  document.createElement( " DIV " );
  3. elm.onclick  =   function () {
  4. return   2   +   2 ;
  5. }
  6. }
  7. for  ( var  i  =   0 ; i   10000 ; i ++ ) {
  8. leakmaybe();
  9. }

btw: 
关于Closure的知识,大家可以看看http://jibbering.com/faq/faq_notes/closures.html这篇文章,习惯中文也可以看看zkjbeyond的blog,他对Closure这篇文章进行了简要的翻译:http://www.blogjava.net/zkjbeyond/archive/2006/05/19/47025.html。 之所以会有这一系列的问题,关键就在于javascript是种函数式脚本解析语言,因此javascript中“函数中的变量的作用域是定义作用域,而 不是动态作用域”,这点在犀牛书《JavaScript: The Definitive Guide》中的“Funtion”一章中有所讨论。 
http://support.microsoft.com/default.aspx?scid=KB;EN-US;830555中也对这个问题举了很详细的例子。

一些 简单的解决方案

目前大多数ajax前端的javascript framework都利用对事件的管理,解决了该问题。

如果你需要自己解决这个问题,可以参考以下的一些方法:

http://outofhanwell.com/ieleak/index.php?title=Main_Page:有个不错的检测工具 
http://youngpup.net/2005/0221010713 中提到:可以利用递归Dom树,解除event绑定,从而解除循环引用:

Html代码  

  1. if (window.attachEvent) {
  2. var clearElementProps = [
  3. ‘data‘,
  4. ‘onmouseover‘,
  5. ‘onmouseout‘,
  6. ‘onmousedown‘,
  7. ‘onmouseup‘,
  8. ‘ondblclick‘,
  9. ‘onclick‘,
  10. ‘onselectstart‘,
  11. ‘oncontextmenu‘
  12. ];
  13. window.attachEvent("onunload", function() {
  14. var el;
  15. for(var d = document.all.length;d--;){
  16. el = document.all[d];
  17. for(var c = clearElementProps.length;c--;){
  18. el[clearElementProps[c]] = null;
  19. }
  20. }
  21. });
  22. }

而http://novemberborn.net/javascript/event-cache一文中则通过增加EventCache,从而给出一个相对结构化的解决方案

Html代码  

  1. /*     EventCache Version 1.0
  2. Copyright 2005 Mark Wubben
  3. Provides a way for automagically removing events from nodes and thus preventing memory leakage.
  4. See <http://novemberborn.net/javascript/event-cache> for more information.
  5. This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
  6. */
  7. /*     Implement array.push for browsers which don‘t support it natively.
  8. Please remove this if it‘s already in other code  */
  9. if (Array.prototype.push  ==   null ){
  10. Array.prototype.push  =   function (){
  11. for ( var  i  =   0 ; i  <  arguments.length; i ++ ){
  12. this [ this .length]  =  arguments[i];
  13. };
  14. return   this .length;
  15. };
  16. };
  17. /*     Event Cache uses an anonymous function to create a hidden scope chain.
  18. This is to prevent scoping issues.  */
  19. var  EventCache  =   function (){
  20. var  listEvents  =  [];
  21. return  {
  22. listEvents : listEvents,
  23. add :  function (node, sEventName, fHandler, bCapture){
  24. listEvents.push(arguments);
  25. },
  26. flush :  function (){
  27. var  i, item;
  28. for (i  =  listEvents.length  -   1 ; i  >=   0 ; ii  =  i  -   1 ){
  29. item  =  listEvents[i];
  30. if (item[ 0 ].removeEventListener){
  31. item[ 0 ].removeEventListener(item[ 1 ], item[ 2 ], item[ 3 ]);
  32. };
  33. /*  From this point on we need the event names to be prefixed with ‘on"  */
  34. if (item[ 1 ].substring( 0 ,  2 )  !=   " on " ){
  35. item[ 1 ]  =   " on "   +  item[ 1 ];
  36. };
  37. if (item[ 0 ].detachEvent){
  38. item[ 0 ].detachEvent(item[ 1 ], item[ 2 ]);
  39. };
  40. item[ 0 ][item[ 1 ]]  =   null ;
  41. };
  42. }
  43. };
  44. }();

使用方法也很简单:

Html代码  

  1. <script type="text/javascript">
  2. function addEvent(oEventTarget, sEventType, fDest){
  3. if(oEventTarget.attachEvent){
  4. oEventTarget.attachEvent("on" + sEventType, fDest);
  5. } elseif(oEventTarget.addEventListener){
  6. oEventTarget.addEventListener(sEventType, fDest, true);
  7. } elseif(typeof oEventTarget[sEventType] == "function"){
  8. var fOld = oEventTarget[sEventType];
  9. oEventTarget[sEventType] = function(e){ fOld(e); fDest(e); };
  10. } else {
  11. oEventTarget[sEventType] = fDest;
  12. };
  13. /* Implementing EventCache for all event systems */
  14. EventCache.add(oEventTarget, sEventType, fDest, true);
  15. };
  16. function createLeak(){
  17. var body = document.body;
  18. function someHandler(){
  19. return body;
  20. };
  21. addEvent(body, "click", someHandler);
  22. };
  23. window.onload = function(){
  24. var i = 500;
  25. while(i > 0){
  26. createLeak();
  27. ii = i - 1;
  28. }
  29. };
  30. window.onunload = EventCache.flush;
  31. </script>

http://talideon.com/weblog/2005/03/js-memory-leaks.cfm 一文中的方法类似:

Html代码  

  1. /*
  2. * EventManager.js
  3. * by Keith Gaughan
  4. *
  5. * This allows event handlers to be registered unobtrusively, and cleans
  6. * them up on unload to prevent memory leaks.
  7. *
  8. * Copyright (c) Keith Gaughan, 2005.
  9. *
  10. * All rights reserved. This program and the accompanying materials
  11. * are made available under the terms of the Common Public License v1.0
  12. * (CPL) which accompanies this distribution, and is available at
  13. * http://www.opensource.org/licenses/cpl.php
  14. *
  15. * This software is covered by a modified version of the Common Public License
  16. * (CPL), where Keith Gaughan is the Agreement Steward, and the licensing
  17. * agreement is covered by the laws of the Republic of Ireland.
  18. */
  19. //  For implementations that don‘t include the push() methods for arrays.
  20. if  ( ! Array.prototype.push) {
  21. Array.prototype.push  =   function (elem) {
  22. this [ this .length]  =  elem;
  23. }
  24. }
  25. var  EventManager  =  {
  26. _registry:  null ,
  27. Initialise:  function () {
  28. if  ( this ._registry  ==   null ) {
  29. this ._registry  =  [];
  30. //  Register the cleanup handler on page unload.
  31. EventManager.Add(window,  " unload " ,  this .CleanUp);
  32. }
  33. },
  34. /* *
  35. * Registers an event and handler with the manager.
  36. *
  37. * @param  obj         Object handler will be attached to.
  38. * @param  type        Name of event handler responds to.
  39. * @param  fn          Handler function.
  40. * @param  useCapture  Use event capture. False by default.
  41. *                     If you don‘t understand this, ignore it.
  42. *
  43. * @return True if handler registered, else false.
  44. */
  45. Add:  function (obj, type, fn, useCapture) {
  46. this .Initialise();
  47. //  If a string was passed in, it‘s an id.
  48. if  ( typeof  obj  ==   " string " ) {
  49. obj  =  document.getElementById(obj);
  50. }
  51. if  (obj  ==   null   ||  fn  ==   null ) {
  52. return   false ;
  53. }
  54. //  Mozilla/W3C listeners?
  55. if  (obj.addEventListener) {
  56. obj.addEventListener(type, fn, useCapture);
  57. this ._registry.push({obj: obj, type: type, fn: fn, useCapture: useCapture});
  58. return   true ;
  59. }
  60. //  IE-style listeners?
  61. if  (obj.attachEvent  &&  obj.attachEvent( " on "   +  type, fn)) {
  62. this ._registry.push({obj: obj, type: type, fn: fn, useCapture:  false });
  63. return   true ;
  64. }
  65. return   false ;
  66. },
  67. /* *
  68. * Cleans up all the registered event handlers.
  69. */
  70. CleanUp:  function () {
  71. for  ( var  i  =   0 ; i  <  EventManager._registry.length; i ++ ) {
  72. with  (EventManager._registry[i]) {
  73. //  Mozilla/W3C listeners?
  74. if  (obj.removeEventListener) {
  75. obj.removeEventListener(type, fn, useCapture);
  76. }
  77. //  IE-style listeners?
  78. else   if  (obj.detachEvent) {
  79. obj.detachEvent( " on "   +  type, fn);
  80. }
  81. }
  82. }
  83. //  Kill off the registry itself to get rid of the last remaining
  84. //  references.
  85. EventManager._registry  =   null ;
  86. }
  87. };

使用起来也很简单

Html代码  

  1. <html>
  2. <head>
  3. <script type=text/javascript src=EventManager.js></script>
  4. <script type=text/javascript>
  5. function onLoad() {
  6. EventManager.Add(document.getElementById(testCase),click,hit );
  7. returntrue;
  8. }
  9. function hit(evt) {
  10. alert(click);
  11. }
  12. </script>
  13. </head>
  14. <body onload=‘javascript: onLoad();‘>
  15. <div id=‘testCase‘ style=‘width:100%; height: 100%; yellow;‘>
  16. <h1>Click me!</h1>
  17. </div>
  18. </body>
  19. </html>

google map api同样提供了一个类似的函数用在页面的unload事件中,解决Closure带来的内存泄露问题。 
当然,如果你不嫌麻烦,你也可以为每个和native object有关的就阿vascript object编写一个destoryMemory函数,用来手动调用,从而手动解除Dom对象的事件绑定。

还有一种就是不要那么OO,抛弃Dom的一些特性,用innerHTML代替appendChild,避开循环引用。详细见http://birdshome.cnblogs.com/archive/2005/02/16/104967.html中的讨论贴。

Cross-Page Leaks

Cross-Page Leaks和下一节提到的Pseudo-Leaks在我看来,就是IE的bug, 虽然MS死皮赖脸不承认:)

大家可以看看这段例子代码:

Html代码  

  1. < html >
  2. < head >
  3. < script language = " JScript " >
  4. function  LeakMemory()  // 这个函数会引发Cross-Page Leaks
  5. {
  6. var  hostElement  =  document.getElementById( " hostElement " );
  7. //  Do it a lot, look at Task Manager for memory response
  8. for (i  =   0 ; i  <   5000 ; i ++ )
  9. {
  10. var  parentDiv  =
  11. document.createElement( " <div onClick=‘foo()‘> " );
  12. var  childDiv  =
  13. document.createElement( " <div onClick=‘foo()‘> " );
  14. //  This will leak a temporary object
  15. parentDiv.appendChild(childDiv);
  16. hostElement.appendChild(parentDiv);
  17. hostElement.removeChild(parentDiv);
  18. parentDiv.removeChild(childDiv);
  19. parentDiv  =   null ;
  20. childDiv  =   null ;
  21. }
  22. hostElement  =   null ;
  23. }
  24. function  CleanMemory()  // 而这个函数不会引发Cross-Page Leaks
  25. {
  26. var  hostElement  =  document.getElementById( " hostElement " );
  27. //  Do it a lot, look at Task Manager for memory response
  28. for (i  =   0 ; i  <   5000 ; i ++ )
  29. {
  30. var  parentDiv  =   document.createElement( " <div onClick=‘foo()‘> " );
  31. var  childDiv  =   document.createElement( " <div onClick=‘foo()‘> " );
  32. //  Changing the order is important, this won‘t leak
  33. hostElement.appendChild(parentDiv);
  34. parentDiv.appendChild(childDiv);
  35. hostElement.removeChild(parentDiv);
  36. parentDiv.removeChild(childDiv);
  37. parentDiv  =   null ;
  38. childDiv  =   null ;
  39. }
  40. hostElement  =   null ;
  41. }
  42. </ script >
  43. </ head >
  44. < body >
  45. < button onclick = " LeakMemory() " > Memory Leaking Insert </ button >
  46. < button onclick = " CleanMemory() " > Clean Insert </ button >
  47. < div id = " hostElement " ></ div >
  48. </ body >
  49. </ 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就可以了, 所以也就不会造成内存泄露了

详细原因,大家可以看看http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp这篇文章。

btw: 
IE 6中垃圾回收算法,就是从那些直接"in scope"的对象开始进行mark清除的: 
Every variable which is "in scope" is called a "scavenger". A scavenger may refer to a number, an object, a string, whatever. We maintain a list of scavengers – variables are moved on to the scav list when they come into scope and off the scav list when they go out of scope.

Pseudo-Leaks

这个被称为“秀逗泄露”真是恰当啊:) 
看看这个例子:

Html代码  

  1. < html >
  2. < head >
  3. < script language = " JScript " >
  4. function  LeakMemory()
  5. {
  6. //  Do it a lot, look at Task Manager for memory response
  7. for (i  =   0 ; i  <   5000 ; i ++ )
  8. {
  9. hostElement.text  =   " function foo() { } " ;//看内存会不断增加
  10. }
  11. }
  12. </ script >
  13. </ head >
  14. < body >
  15. < button onclick = " LeakMemory() " > Memory Leaking Insert </ button >
  16. < script id = " hostElement " > function  foo() { } </ script >
  17. </ body >
  18. </ html >

MS是这么解释的,这不是内存泄漏。如果您创建了许多无法获得也无法释放的对象,那才是内存泄漏。在这里,您将创建许多元素,Internet Explorer 需要保存它们以正确呈现页面。Internet Explorer 并不知道您以后不会运行操纵您刚刚创建的所有这些对象的脚本。当页面消失时(当您浏览完,离开浏览器时)会释放内存。它不会泄漏。当销毁页面时,会中断循 环引用。

唉~~~

详细原因,大家可以看看http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp这篇文章。

其它一些琐碎的注意点

变量定义一定要用var,否则隐式声明出来的变量都是全局变量,不是局部变量; 
全局变量没用时记得要置null; 
注意正确使用delete,删除没用的一些函数属性; 
注意正确使用try...cache,确保去处无效引用的代码能被正确执行; 
open出来的窗口即使close了,它的window对象还是存在的,要记得删除引用; 
frame和iframe的情况和窗口的情况类似。

参考资料

http://jibbering.com/faq/faq_notes/closures.html 
http://javascript.weblogsinc.com/2005/03/07/javascript-memory-leaks/ 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp 
http://72.14.203.104/search?q=cache:V9Bt4_HBzQ8J:jgwebber.blogspot.com/2005/01/dhtml-leaks-like-sieve.html+DHTML+Leaks+Like+a+Sieve+&hl=zh-CN&ct=clnk&cd=9 (这是DHTML Leaks Like a Sieve)一文在google上的cache,原文已经连不上了) 
http://spaces.msn.com/siteexperts/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry 
http://support.microsoft.com/default.aspx?scid=KB;EN-US;830555 
http://www.ajaxtopics.com/leakpatterns.html 
http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx 
http://www.quirksmode.org/blog/archives/2005/02/javascript_memo.html 
http://youngpup.net/2005/0221010713 
http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx = 
http://support.microsoft.com/kb/266071/EN-US ==>IE 5.0至5.5一些版本中的GC bug 
http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html ==>ie 7的改进 
http://erik.eae.net/archives/2006/04/26/23.23.02/ ==>ie 7的改进 
http://www.feedbackarchive.com/spamvampire/today.html ==> Try this script for memory leaks - it leaked 50 megabytes in 15 minutes with firefox on linux: 
http://birdshome.cnblogs.com/archive/2005/02/15/104599.html 
http://www.quirksmode.org/dom/innerhtml.html 
http://www.crockford.com/javascript/memory/leak.html 
《JavaScript: The Definitive Guide》4th Edition 
http://outofhanwell.com/ieleak/index.php?title=Main_Page

关于Javascript的内存泄漏问题的整理稿

时间: 2024-10-13 02:56:03

关于Javascript的内存泄漏问题的整理稿的相关文章

Javascript的内存泄漏分析

作为程序员(更高大尚的称谓:研软件研发)的我们,无论是用Javascript,还是.net, java语言,肯定都遇到过内存泄漏的问题.只不过他们都有GC机制来帮助程序员完成内存回收的事情,如果你是C++开发者(你懂的).....,如果你是前端开发者,肯定在使用Javascript(你或者会说,Js是世界上最棒的语言),但我这里也得告诉你,Js的内存泄漏会来得更为突然,或者让你都无法察觉.本文就带大家领略一下Js的风骚: 一.模块化引起的内存泄漏 代码如下: // module date.js

关于JavaScript的内存泄漏的思考

1. 概念 1) 内存泄漏就是指程序中不再用到的对象依然占用的内存无法释放: 2) 程序中的内存过程:系统分配------程序使用 ------ 程序.系统释放 说到内存泄漏不得不提到垃圾回收机制 2. 垃圾回收机制 目前垃圾回收机制有两种: 1) 引用标记法 优势:简单 劣势:对于循环引用的对象无法清除 2) 标记清除法--解决了循环引用对象 3. 常见的内存泄漏 1)全局变量 对于定义的全局变量,由于挂在window上,除非刷新浏览器,这个变量就永远不会被回收 2)未销毁的定时器和回调函数

javaScript内存泄漏

first: 先理解我们的基本概念,什么是内存泄漏: 答: 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak) 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分

javascript 内存泄漏的学习

概念 内存泄漏: 用动态存储分配函数动态开辟的空间,在使用完毕后未释放, 木有任何指针指向他,结果导致一直占据该内存单元.直到程序结束.(其实说白了就是该内存空间使用完毕之后未回收, 占着茅坑不**)即所谓内存泄漏. 等所有内存都被占完之后, 系统就跪了. 内存分配方式 说道内存泄露,就不得不谈到内存分配的方式.内存分配有三种方式,分别是: 一.静态分配( Static Allocation ):静态变量和全局变量的分配形式.如果把房间看做一个程序,我们可以把静态分配的内存当成是房间里的耐用家具

JavaScript 中的内存泄漏

JavaScript 是一种垃圾收集式语言,这就是说,内存是根据对象的创建分配给该对象的,并会在没有对该对象的引用时由浏览器收回.JavaScript 的垃圾收集机制本身并没有问题,但浏览器在为 DOM 对象分配和恢复内存的方式上却有些出入. Internet Explorer 和 Mozilla Firefox 均使用引用计数来为 DOM 对象处理内存.在引用计数系统,每个所引用的对象都会保留一个计数,以获悉有多少对象正在引用它.如果计数为零,该对象就会被销毁,其占用的内存也会返回 给堆.虽然

JavaScript的闭包和内存泄漏问题

闭包 JavaScript中必须提到的功能最强大的抽象概念之一:闭包.它究竟是做什么的呢? 1 function makeAdder(a) { 2 return function(b) { 3 return a + b; 4 } 5 } 6 var x = makeAdder(5); 7 var y = makeAdder(20); 8 x(6); // 11 9 y(7); // 27 makeAdder这个名字本身应该能说明函数是用来做什么的:他创建了一个新的adder函数,这个函数自身带有

了解 JavaScript 应用程序中的内存泄漏

简介 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分配和释放的具体细节. 许多功能无需考虑内存管理即可实现,但却忽略了它可能在程序中带来重大的问题.不当清理的对象可能会存在比预期要长得多的时间.这些对象继续响应事件和消耗资源.它们可强制浏览器从一个虚拟磁盘驱动器分配内存页,这显著影响了计算机的速度(在极端的情形中,会导致浏览器崩溃). 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在.在最近几

前端开发中javascript闭包会引发内存泄漏么?

本文主要是和大家一起来讨论下javascript的闭包会造成内存泄漏吗?希望通过本文的分享对大家学习javascript有所帮助.  在谈内存泄漏这个问题之前先看看JavaScript的垃圾收集机制,JavaScript 具有自动垃圾收集机制,就是找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间).常用的的方法有两种,即标记清楚和引用计数.  标记清除  JavaScript 中最常用的垃圾收集方式是标记清除(mark-and-s

关于JavaScript内存泄漏的质疑

近几天看了些关于JavaScript内存管理的文章,相对于Java JVM的内存管理,显得简单些. 在学习的过程中,发现有不少网友谈到了循环引用,说循环引用会造成内存泄漏,垃圾回收器无法回收. 实际上,并没有这么可怕,根据小菜目前的了解,这种循环引用造成的内存泄漏,仅仅会发生在低版本的IE浏览器上,现代浏览器是不会这么蠢的. 举个例子,网络上流行的说法大致有如下两种: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta char