网络编程
位置:首页>> 网络编程>> JavaScript>> 关于Javascript的内存泄漏问题(4)

关于Javascript的内存泄漏问题(4)

作者:海啸 来源:海啸博客 发布时间:2008-04-15 07:46:00 

标签:内存,泄露,javascript

Cross-Page Leaks

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

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

<html> 
<head> 
<script language="JScript"> 
// 这个函数会引发Cross-Page Leaks
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 ;
}

// 而这个函数不会引发Cross-Page Leaks
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 ;
}
</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就可以了, 所以也就不会造成内存泄露了

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

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> 
<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> 
</head> 
<body> 
<button onclick=" LeakMemory()"> Memory Leaking Insert </button> 
<script id="hostElement">function foo(){}</script> 
</body> 
</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的情况和窗口的情况类似。

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com