为什么此功能导致内存泄漏

时间:2012-05-09 23:54:03

标签: javascript

function parseAttach(b)
{
    var h="";
    for(i=0;i<b.length;i++)
    {
        var a=b[i];
        switch(a['type'])
        {
            case "image":
                h+='<li class="attach aImg" style="background:#000;border-bottom:2px solid #fff"><img style="max-width:425px;max-height:500px" src="http://img.xiami.com/u/phoo/'+a['file']+'"></li>';
            break;
            case "video":
                h+='<li class="attach aVideo" style="background:#f3f3f3"><span class="MxND" f="'+a['from']+'" d="'+a['id']+'"></span></li>';
            break;
            case "music":
                h+='<li class="attach aMusic"><embed src="http://www.xiami.com/widget/0_'+a['id']+'/singlePlayer.swf" type="application/x-shockwave-flash" width="257" height="33" wmode="transparent"></embed></li>';
            break;
        }
    }
    return h;
}

一旦上面的函数运行,页面就无法进行交互,那个页面的内存和CPU使用率就会一路飙升。

这是传递给此函数的参数b的示例:

[{"type":"video","from":"k6","id":"kyxGTZbD-vQ8Domm-eeHiQ"}]

b.length不超过2,此功能执行不超过三次。如果删除此功能,则不会发生内存泄漏。

更新:

按照@GarethMcCaughan的建议,我将警报(i)添加到循环的顶部,它保持警报0,我前往调用代码:

for(i=0;i<c[0].length;i++)//the breakpoint
{
    ......
    if(t[6].length>0)
    {
        //console.log(t[6].length);
        //var a=parseAttach(t[6]);
        var a="";
        h+='<ul class="attaches">'+a+'</ul>';
    }
   ......
}

正如您在注释中看到的那样,如果我用console.log替换调用,则日志仅显示4次执行。但为什么要重复调用该函数?

然后我发现控制台在循环顶部报告了一个断点(我已将其注释掉),这是函数不断调用的原因吗?

2 个答案:

答案 0 :(得分:0)

在你的两个循环中,你没有将var放在i变量之前。这意味着它是全球性的。如果它是全局的,则两个循环都使用相同 i

for(i=0;i<b.length;i++)

添加var,它应该修复它:

for(var i=0;i<b.length;i++)

编辑:进一步澄清:

for(i=0;i<c[0].length;i++)
{
    ......
    if(t[6].length>0)
    {
        // THIS CALL WILL SET THE GLOBAL i TO t[6].length
        var a=parseAttach(t[6]);
    }
   ......
}

因此,永远不会满足外循环的退出条件,循环的每次迭代都会设置i,以便i永远不会到达c[0].length

答案 1 :(得分:0)

除了一个bug之外,一切似乎都很好:你忘了将计数器变量i置于本地。当从循环调用时,代码将重置外部循环的同名计数器变量(为2,因为这是最大长度)并使其永远不会达到其结束条件:

var i; // this variable will always be referenced
function x(number) {
    for (i=0; i<number; i++)
        dosomething;
}
for (i=0; i<5; i++)
    x(2); // resets i to 2
// => never-ending loop

无限循环将使浏览器挂起,冻结界面,直到代码执行完毕。某些浏览器可能会因长时间运行的脚本而抛出错误,并通过超时实现。