JavaScript是否有内置的stringbuilder类?


Answers:


318

如果必须为Internet Explorer编写代码,请确保选择一个使用数组联接的实现。在IE上使用+or +=运算符连接字符串非常慢。对于IE6尤其如此。在现代浏览器+=上,通常与数组连接一样快。

当我必须执行许多字符串连接时,我通常会填充一个数组并且不使用字符串生成器类:

var html = [];
html.push(
  "<html>",
  "<body>",
  "bla bla bla",
  "</body>",
  "</html>"
);
return html.join("");

请注意,这些push方法接受多个参数。


7
而且,如果您要内联生成输出,或者所有成员都是文字[foo(), "bar", "baz"].join("");,那么也可以使用。
匿名

1
尽管人们可能无法期望Dropbox链接能够保持工作将近3年,但我对这种比较感到好奇-如果这种比较仍然成立的话。
Cornelius 2012年

1
@DaveWard,您的链接已断开:(
Ivan Kochurkin

我发现这比字符串+字符串+字符串更具可读性
Andrew Ehrlich 2014年

12
我不知道push可以接受多个参数。您学习的随机事物。
Carcigenicate's

55

我只是在http://jsperf.com/javascript-concat-vs-join/2上重新检查了性能。测试用例连接或连接字母1,000次。

在当前的浏览器(FF,Opera,IE11,Chrome)中,“ concat”比“ join”快4-10倍。

在IE8中,两者返回的结果大致相同。

不幸的是,在IE7中,“ join”的速度约为100倍。


3
谢谢你 这应该在答案列表中增加。在IE10上,它的运行速度也要快得多(我知道这不是现代的浏览器,但对于任何潜在的NMCI开发人员,我都会提到它)。
詹姆斯·威尔逊

@Andreas我相信您的测试在Chrome中遇到了一条代码路径,在该路径中它从未做过实际的连接,因为从未读取过该字符串。即使强制执行,执行速度仍然要快得多:jsperf.com/yet-another-string-concat-test/1
Joseph Lennox

37

不,不存在对构建字符串的内置支持。您必须改为使用串联。

当然,您可以将字符串的不同部分组成一个数组,然后调用join()该数组,但这取决于如何在所使用的JavaScript解释器中实现联接。

我做了一个实验,比较str1+str2方法与array.push(str1, str2).join()方法的速度。代码很简单:

var iIterations =800000;
var d1 = (new Date()).valueOf();
str1 = "";
for (var i = 0; i<iIterations; i++)
    str1 = str1 + Math.random().toString();
var d2 = (new Date()).valueOf();
log("Time (strings): " + (d2-d1));

var d3 = (new Date()).valueOf();
arr1 = [];
for (var i = 0; i<iIterations; i++)
    arr1.push(Math.random().toString());
var str2 = arr1.join("");
var d4 = (new Date()).valueOf();
log("Time (arrays): " + (d4-d3));

我在Windows 7 x64上的Internet Explorer 8和Firefox 3.5.5中进行了测试。

在开始的时候,我测试了少量的迭代(几百,几千个项目)。结果是不可预测的(有时字符串连接花费0毫秒,有时花费16毫秒,与数组连接相同)。

当我将计数增加到50,000时,在不同的浏览器中结果是不同的-在Internet Explorer中,字符串连接速度更快(94毫秒),连接速度更慢(125毫秒),而在Firefox中,数组连接速度更快(113毫秒)字符串连接(117毫秒)。

然后我将计数增加到500'000。现在array.join()慢于字符串连接两个浏览器:字符串连接是在Internet Explorer 937毫秒,1155毫秒在Firefox中,阵列在Internet Explorer中加入1265,并且在Firefox 1207毫秒。

我可以在Internet Explorer中测试而没有“脚本执行时间太长”的最大迭代次数为850,000。然后Internet Explorer的字符串连接为1593,数组连接为2046,而Firefox的字符串连接为2101,数组连接为2249。

结果 -如果迭代次数很少,则可以尝试使用array.join(),因为在Firefox中它可能更快。当数量增加时,该string1+string2方法会更快。

更新

我在Internet Explorer 6(Windows XP)上进行了测试。如果我尝试了100,000次以上的迭代测试,该过程将立即停止响应并永无止境。经过40,000次迭代,结果是

Time (strings): 59175 ms
Time (arrays): 220 ms

这意味着-如果您需要支持Internet Explorer 6,请选择array.join()比字符串连接更快的方法。


join()是ECMAScript和afaik的一部分,每个JavaScript解释程序都实现它。为什么会“依赖”?
伊莱·格雷

他的意思是它是如何实现的...如果以某种方式实现,即以循环方式连续添加字符串,而不是立即创建所有字符串,那么使用join将毫无意义
John

是的,这就是我的真正意思。请原谅我的英语;-)我添加了比较结果,比较了哪种方法在两种浏览器中的运行速度。您可以看到,这是不同的。
naivists 2010年

2
IE6和往常一样是一个例外:)
Gordon Tucker 2010年

10
IE6的人们习惯于让一切变得非常缓慢。我不认为他们会怪你。
罗德韦克2012年

8

该代码看起来像您希望进行的路线,但进行了一些更改。

您将需要更改append方法看起来像这样。我将其更改为接受数字0,并使其返回,this以便您可以链接附录。

StringBuilder.prototype.append = function (value) {
    if (value || value === 0) {
        this.strings.push(value);
    }
    return this;
}

为什么只接受非NaN数字和非空字符串?您的方法将不接受null,,false空字符串undefinedNaN
伊莱·格雷

@Elijah-我更喜欢通过保留有效的字符串和数字来保持StringBuilder类的清洁。这只是个人喜好。
Gordon Tucker 2010年

5

JavaScript的ECMAScript 6版本(也称为ECMAScript 2015)引入了字符串文字

var classType = "stringbuilder";
var q = `Does JavaScript have a built-in ${classType} class?`;

注意,反引号而不是单引号将字符串引起来。


17
这如何回答这个问题?
彼得·莫滕森

@Peter Mortensen,此答案仅提供了另一种构建字符串的方法。原始张贴者未指定要搜索的字符串生成器功能类型。
Theophilus '18

1
这不能回答问题。完全没有
Massimiliano Kraus

3

在C#中,您可以执行以下操作

 String.Format("hello {0}, your age is {1}.",  "John",  29) 

在JavaScript中,您可以执行以下操作

 var x = "hello {0}, your age is {1}";
 x = x.replace(/\{0\}/g, "John");
 x = x.replace(/\{1\}/g, 29);

2
我非常怀疑运行正则表达式代替字符串连接会更有效
tic

此外,这是一个糟糕的实现。如果{0}替换的字符串包含,它将断开{1}
ikegami

@ikegami字符串不是变量,而是常量,因此您知道先验内容是什么。
体育

@sports,在代码中复制并粘贴所有内容是一个更糟糕的主意。
ikegami

一个带有$ 1和$ 2的衬里替换了非捕获组:x..replace(/([\ s \ S] *?)\ {0 \}([\ s \ S] *?)\ {1 \} / g,“ $ 1Tom $ 225”)
T.CK,

1

对于那些感兴趣的人,这是调用Array.join的替代方法:

var arrayOfStrings = ['foo', 'bar'];
var result = String.concat.apply(null, arrayOfStrings);
console.log(result);

如预期的那样,输出为字符串'foobar'。在Firefox中,此方法的性能优于Array.join,但由+级联的性能优于。由于String.concat要求将每个段指定为单独的参数,因此调用者受到执行JavaScript引擎施加的任何参数计数限制的限制。请查看Function.prototype.apply()的文档以获取更多信息。


由于未定义“ String.concat”,因此这在Chrome中失败。相反,您可以使用``.concat.apply('',arrayOfStrings)。但这仍然是一个非常缓慢的方法。
安德里亚斯(Andreas)

1

我已经定义了这个功能:

function format() {
        var args = arguments;
        if (args.length <= 1) { 
            return args;
        }
        var result = args[0];
        for (var i = 1; i < args.length; i++) {
            result = result.replace(new RegExp("\\{" + (i - 1) + "\\}", "g"), args[i]);
        }
        return result;
    }

可以像c#那样调用:

 var text = format("hello {0}, your age is {1}.",  "John",  29);

结果:

你好约翰,你的年龄是29岁。


1
我喜欢...看起来像c#
Ayo Adesina

2
这个答案与问题无关。
Massimiliano Kraus

0

当我发现自己在JavaScript中进行大量字符串连接时,我开始寻找模板。Handlebars.js可以很好地保持HTML和JavaScript的可读性。http://handlebarsjs.com


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.