JavaScript和非常长的字符串

3
我遇到了以下代码的问题:
function showTableData()
{
    var tableArray;
    var x = 0;
    var theHTML;

    for (i = 0; i < 7032; i++)
    {
        if (x = 0)
        {
            theHTML = '<tr>' + 
                '<th scope="row" class="spec">' + partNum[i] + '</th>' + 
                '<td>' + Msrp[i] + '</td>' + 
                '<td>' + blah[i] + '</td>' + 
                '<td>' + blahs[i] + '</td>' + 
            '</tr>' + theHTML;
            x++;
        }else{
            theHTML = '<tr>' + 
                '<th scope="row" class="specalt">' + partNum[i] + '</th>' + 
                '<td class="alt">' + Msrp[i] + '</td>' + 
                '<td class="alt">' + blah[i] + '</td>' + 
                '<td class="alt">' + blahs[i] + '</td>' + 
            '</tr>' + theHTML;
            x--;
        }
    }
    theHTML = '<table id="mytable" cellspacing="0">' + 
    '<tr>' + 
        '<th scope="col" abbr="Configurations" class="nobg">Part Number</th>' + 
        '<th scope="col" abbr="Dual 1.8">Msrp Price</th>' + 
        '<th scope="col" abbr="Dual 2">blahs Price</th>' + 
    '<th scope="col" abbr="Dual 2.5">Low Price</th>' + 
    '</tr>' + theHTML + '</table>';

    $('#example').append(theHTML);
}
 </script>

 <div id="example">
 </div>

问题在于 $('#example').append(theHTML); 从未执行(或显示在页面上)。我认为这是因为字符串太长了!它的数组中有超过7,000个项目,所以我不确定是否是这个原因或其他原因?

任何帮助都将是极好的!谢谢!

大卫


1
如果 (x=0) (第9行) 应该是 if (x==0),不确定这是否只是一个打字错误。 - Hemlock
你确定这个函数被正确地调用了吗? - Ryan Li
2
一些建议。使用 push 构建数组而不是字符串拼接。然后在附加 HTML 之前使用 array.join('')。性能更好。 - Hemlock
谢谢,Hemlock。已经修复了那个错误。 - StealthRT
5个回答

11
除了应该使用if (i % 2 === 0)而不是if (x = 0)外,您真的应该通过使用Array.join()方法而不是连接字符串来提高性能。这将类似于C#或Java中的StringBuilder
例如:
function showTableData()
{
    var tableArray;
    var theHTML = [];
    theHTML.push('<table id="mytable" cellspacing="0">',
    '<tr>', 
        '<th scope="col" abbr="Configurations" class="nobg">Part Number</th>', 
        '<th scope="col" abbr="Dual 1.8">Msrp Price</th>',
        '<th scope="col" abbr="Dual 2">blahs Price</th>', 
    '<th scope="col" abbr="Dual 2.5">Low Price</th>', 
    '</tr>');

    for (var i = 0; i < 7032; i++)
    {
        if (i % 2 == 0)
        {
             theHTML.push('<tr>', 
                 '<th scope="row" class="spec">', partNum[i], '</th>',
                 '<td>', Msrp[i], '</td>', 
                 '<td>', blah[i], '</td>', 
                 '<td>', blahs[i], '</td>', 
             '</tr>');
        } else {
             theHTML.push('<tr>',
                 '<th scope="row" class="specalt">', partNum[i], '</th>', 
                 '<td class="alt">', Msrp[i], '</td>', 
                 '<td class="alt">', blah[i], '</td>', 
                 '<td class="alt">', blahs[i], '</td>',
             '</tr>');
        }
    }
    theHTML.push('</table>');

    $('#example').append(theHTML.join(''));
}
 </script>

 <div id="example">
 </div>

将字符串'my' + ' appended' + ' string'追加比连接字符串['my', ' joined', ' string'].join('')慢的原因是JavaScript字符串是不可变的,所以在前一种情况下,每次连接2个字符串时都会创建第三个字符串,这是与添加新条目到数组相比非常昂贵的操作。
另请参见使用Array.push()和Array.join()相同原则构建的Javascript StringBuilder项目
在IE中进行了10,000次字符串连接后,该项目的性能提高从1分钟减少到0.23秒。 更新:在for循环内部添加额外的Array.join()调用来替换字符串连接,以进一步提高客户端渲染速度。+ 添加更好的StringBuilder链接。 更进一步的更新:按照Hemlock的建议进行以下修改:
  1. 通过在for循环中定义var i = 0来删除对全局作用域变量的使用。
  2. 使用Array.push()的多个参数同时推入多个字符串。

这段代码仍有很多可以改进的空间。最糟糕的问题是 i 从未被声明,应该改为 for var i=0;。没有必要使用额外的数组,因为 push 可以接受多个参数,只需要一个 join 即可。我不理解为什么要重复所有的代码来添加行,看起来那只是用来添加 alt 样式的。可以通过在 tr 上加一个类和一些优秀的 CSS 来实现。这里有一个示例:http://jsbin.com/itego4/3/edit - Hemlock
@Hemlock,我对推送语句和本地作用域变量进行了更改,但保留了if-then-else和css不变。虽然我同意你的看法,但我认为这超出了问题的范围,更改css可能会产生其他副作用。 - Steven de Salas
非常好,@steven - 我不知道我可以像那样附加长的HTML字符串 ;) - Sagive
@StevendeSalas 我在 http://jsperf.com/string-concat-without-sringbuilder/3 上的测试表明,StringBuilder 带来的方法开销比好处更多,而字符串拼接比 Array.join 技巧更快... 你有什么评论吗? - Ruan Mendes
嗨Juan,我不能保证你测试的统计数据,但我知道自从谷歌推出了带有各种JS引擎编译时性能优化的Chrome浏览器,像这样的所有其他浏览器都效仿了它。也许这个答案现在只适用于旧版本的IE。 - Steven de Salas

3

我看到的一个错误是,if (x = 0) 应该改为 if (x == 0)。除此之外,对我来说它似乎可以工作:http://jsfiddle.net/9vvJ6/


2
这一行:

if (x = 0)

难道不应该是

if (x == 0)

可能是这里的错误导致了脚本无法执行。

如果 (x = 0) 是正确的语法,它不会导致错误。如果将 0 分配给 x 是成功的,则为 true... - miqbal

1
如果您已经在使用jQuery,您可能想考虑在这里使用jQuery模板,它很可能会清理您的代码并使您的生活更轻松。可能会有性能方面的权衡(但我认为JavaScript中的字符串插值比字符串连接更快,所以这甚至可能更快?),但无论您失去或获得了什么性能,它都是一个更优雅的解决方案。您可以将整个模板放在一个地方(也许是外部文件,或者是隐藏在文档的DOM中的某些部分,我还没有使用它足够多来告诉您最佳实践是什么),然后使用jQuery模板进行字符串替换。有多个基于jQuery的模板框架,但我链接的那个正在成为jQuery的官方一部分。

1
问题出在 .append jQuery 函数上。你不能使用 .html 或者 .append 函数处理过长的字符串。相反,你需要使用 .innerHTML。
试一下这个方法。
document.getElementById('example').innerHTML=theHTML.join('');

这并不是严格正确的。正如 jQuery 文档所述:“此 [html] 方法使用浏览器的 innerHTML 属性” (http://api.jquery.com/html/#html2)。 - beterthanlife
值得注意的是,html() 方法比直接使用 innerHTML 方法慢近两倍(https://dev59.com/CnNA5IYBdhLWcg3wL6oc)。 - beterthanlife

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接