Javascript内存泄漏/性能问题?

Tom*_*Tom 2 javascript memory dom

我只是不能为我的生活弄清楚Internet Explorer中的内存泄漏.

insertTagssimple接受字符串str并将每个单词放在HTML的开始和结束标记内(通常是锚标记).transliterate用于阿拉伯数字,用&#.. n替换正常数字0-9; 他们的阿拉伯语对应的XML身份.

fragment = document.createDocumentFragment();
for (i = 0, e = response.verses.length; i < e; i++)
{
    fragment.appendChild((function(){
        p = document.createElement('p');
        p.setAttribute('lang', (response.unicode) ? 'ar' : 'en');
        p.innerHTML = ((response.unicode) ? (response.surah + ':' + (i+1)).transliterate() : response.surah + ':' + (i+1)) + ' ' + insertTags(response.verses[i], '<a href="#" onclick="window.popup(this);return false;" class="match">', '</a>');
        try { return p } finally { p = null; }
    })());
}
params[0].appendChild( fragment );
fragment = null;
Run Code Online (Sandbox Code Playgroud)

我会喜欢除MSDN和about.com之外的一些链接,因为他们都没有充分向我解释为什么我的脚本会泄漏内存.我确信这是问题所在,因为没有它,一切都会快速运行(但没有显示).

我已经读到做很多DOM操作可能很危险,但for循环最多286次(古兰经中最长的surah 2中的经文#).

*IE7和IE8中的内存泄漏,不确定大约6,但在Safari 4,FF 3.6,Opera 10.5,Chrome 5 ......中工作得非常好

Jef*_*ang 6

变量的范围是函数,而不是/ else/for/while/etc.块.每次打电话

fragment.appendChild((function() { ...
Run Code Online (Sandbox Code Playgroud)

您正在创建一个新功能(新范围).这个新函数引用了iresponse变量.所以现在,i并将response范围限定为外部函数和新函数.

这不足以泄漏内存.(i并且response是在新功能完成后超出范围的正常变量)

但是,您p在新函数中创建一个DOM元素,并在外部函数中引用它(将它fragment.appendChild作为参数返回给调用).现在考虑一下:你有外部作用域fragment引用p从内部作用域创建的DOM,它需要使用外部作用域中的iresponse变量来创建DOM元素.

fragmentpDOM对象,每个具有彼此参考.尽管你的企图零时的引用计数被归零变量的指针,p=nullfragment = null不会摆脱所有引用.将fragment仍具有到内的参考p,其仍具有到外的参考response变量.由于这种剩余的循环依赖性,这两个"范围"永远不会被垃圾收集.

任何人,如果我犯了任何错误,请纠正我.


至于解决方案,只是不要使用内部功能!

fragment = document.createDocumentFragment();
for (var i = 0, var e = response.verses.length; i < e; i++)
{
    var p = document.createElement('p');
    p.setAttribute('lang', (response.unicode) ? 'ar' : 'en');
    p.innerHTML = ((response.unicode) ? (response.surah + ':' + (i+1)).transliterate() : response.surah + ':' + (i+1)) + ' ' + insertTags(response.verses[i], '<a href="#" onclick="window.popup(this);return false;" class="match">', '</a>');
    fragment.appendChild(p);
}
params[0].appendChild( fragment );
Run Code Online (Sandbox Code Playgroud)