“+”运算符比StringBuffer.append()慢吗?

91

在我的团队中,我们通常会像这样进行字符串拼接:

var url = // some dynamically generated URL
var sb = new StringBuffer();
sb.append("<a href='").append(url).append("'>click here</a>");
显然,以下内容更易读:
var url = // some dynamically generated URL
var sb = "<a href='" + url + "'>click here</a>";

但是 JS 专家们声称,+ 运算符比 StringBuffer.append() 方法的性能要差。这是真的吗?


98
JavaScript 中没有 StringBuffer。 - Tomas
7
唐,你是在指Java吗? - James McMahon
1
我知道这里的基本问题是关于字符串连接,但是在创建像这样的HTML元素时,您应该小心。如果url包含'\n,则您的示例可能会出错。 - styfle
1
我不知道为什么这个问题没有因为缺乏明确性而被关闭。相反,它有91个赞。JS中没有StringBuffer,那么这怎么可能是一个有效的问题呢? - Omkar76
这个问题不够清晰(正如其他人所指出的),而且也是重复的https://dev59.com/7WQn5IYBdhLWcg3wn4NS - Inigo
显示剩余2条评论
13个回答

102

你的示例不太合适,因为性能差异非常小。在你的示例中,可读性应该优先于性能,因为一种方法与另一种方法相比的性能提高是微不足道的。只有当你需要进行多次连接时,数组(StringBuffer)才会显示出其优势。即便如此,在不同的浏览器上,效果也可能因人而异。

下面是一份详细的性能分析,展示了在许多不同的浏览器上使用所有不同的JavaScript连接方法的性能:String Performance an Analysis

join() once, concat() once, join() for, += for, concat() for

更多信息:
Ajaxian >> String Performance in IE: Array.join vs += continued


10
关于这张图,如果不明显的话,较低的数值意味着更好。 - Teekin
1
首先,随着IE7的性能改进,我们不再需要考虑在进行大规模字符串操作时使用替代路径;在迭代情况下使用Array.join与在相同情况下使用+=没有太大的优势。此外,与IE6的差异足够小,可以让您不必为该特定版本而烦恼。 - Chris S
2
@Chris,那不是真的。比较这两个IE7代码片段:http://jsfiddle.net/9uS4n/5/(快速)与http://jsfiddle.net/9uS4n/2/(慢)。使用“join()”技术至少提高了1000倍的性能。 - Kirk Woll
很好的解释。请也查看这个链接: http://www.iliadraznin.com/2012/03/string-concatenation-array-join-performance-javascript/#comment-938 - will824

46

在当今世界上,唯一真正受此影响的浏览器是 Internet Explorer。(版本5、6和7非常慢,8不会出现同样的退化。) 此外,IE的字符串越长,它就会变得越慢。

如果您需要连接长字符串,请使用数组.join技术。(或某个StringBuffer包装器,以提高可读性。) 但如果您的字符串很短,就没有必要麻烦了。


37

是的,这是真的,但你不应该在意。选择更容易阅读的内容。如果必须对您的应用程序进行基准测试,则应专注于瓶颈。

我猜字符串连接不会成为你的瓶颈。


33

同意Michael Haren的看法。

如果性能确实是一个问题,还可以考虑使用数组和join方法。

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));

3
我知道已经选择了一个正确的答案,但这个答案有一个更有用的例子。 - Jason Sperske
1
哇,真是太棒了。在IE7中比较这两个fiddles:http://jsfiddle.net/9uS4n/5/(快速)与http://jsfiddle.net/9uS4n/2/(慢速)。使用这种技术,性能至少提高了1000倍。 - Kirk Woll
@KirkWoll: 以后可能要使用jsPerf,这样我们可以轻松比较结果。 - rvighne
最近我也一直在做这个,代码风格类似于 .NET 的 StringBuilder,var sb = []; sb.push("第一部分"); sb.push("第二部分"); return sb.join(''); - Sam Jones
这个jsPerf https://jsperf.com/join-concat/2 在https://dev59.com/7WQn5IYBdhLWcg3wn4NS#16696775提到,似乎表明`+=`更快。 - Ciro Santilli OurBigBook.com

18

试试这个:

var s = ["<a href='", url, "'>click here</a>"].join("");

好的,你在回答中链接的帖子特意试图反驳我的回答所提出的Array.join的“神话”。所以也许不是这样。我只是发表了我在实践中看到的更快的方法。 - Rahul
喜欢这种字符串拼接的方法。 - bkwdesign

8
JavaScript没有原生的StringBuffer对象,所以我假设这是你正在使用的库或者不寻常的主机环境的特性(即不是浏览器)。
我怀疑一个(用JS编写的)库能够产生更快的效果,尽管原生的StringBuffer对象可能会更快。如果你正在浏览器中运行,则可以使用Firebug来提供Firefox中JS引擎的分析器,从而得出最终答案。

8

正如一些用户已经指出的那样:这对于小字符串来说是不相关的。

而且Firefox、Safari或Google Chrome中的新JavaScript引擎会进行优化,因此

"<a href='" + url + "'>click here</a>";

与...一样快

["<a href='", url, "'>click here</a>"].join("");

6

以 Knuth 的话说,“过早优化是一切罪恶的根源!”在最终结果中,微小的差异很可能不会产生太大影响;我会选择更可读的方式。


1
传统上,StringBuffer 被用于连接字符串,因为前者的时间复杂度为 O(N),而后者为 O(N^2),因此对于大 N 来说差异是显著的(但对于小 N 来说则不然)。无论如何,在 JavaScript 中,O(N^2) 的情况可能取决于所使用的环境。 - redcalx

4
更易读的方法会在人们查看代码时节省可察觉的时间,而“更快”的方法仅会浪费不可察觉且可能可以忽略的时间,当人们浏览页面时。我知道这篇文章有点无聊,但我无意中将一些完全不同的内容发布在了这里,因为我以为这是另一个帖子,而我不知道如何删除帖子,我的错...

3

使用jspref.com可以轻松设置快速基准测试并检查JavaScript性能变化。当提出这个问题时可能还没有这个网站,但对于遇到这个问题的人们,他们应该看看这个网站。

我在http://jsperf.com/string-concat-methods-test上对各种连接方法进行了快速测试。


从那个看起来,现在使用加号运算符进行字符串连接绝对是正确的方法。除非我读错了。这完全有可能。 - Richard

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