数组连接 vs 字符串拼接

83

哪种方法更快?

数组连接:

var str_to_split = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
var myarray = str_to_split.split(",");

var output=myarray.join("");

字符串拼接:

var str_to_split = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
var myarray = str_to_split.split(",");

var output = "";
for (var i = 0, len = myarray.length; i<len; i++){
    output += myarray[i];
}

取决于你想要什么。String方法稍微简单一些。使用数组join的方式可能会更快一些(你可以在jsperf.com上进行测试)。 - andrewmu
for循环的作用是什么?只是复制还是在其中进行处理?有更快的方法可以复制数组。 - epascarello
epascarello,它们只是用来测试这两种方法的愚蠢示例。 - ajax333221
1
我记得几年前读过一些文章引用性能统计数据来证明数组方法比字符串拼接更快,但即使在那时,这种情况也因浏览器而异。在我看来,这些类型的性能问题似乎每次下一代浏览器推出时都会反转。 - nnnnnn
看起来在 Chrome 53 和 Firefox 48 中,使用迭代比使用数组连接(链接)更快,速度超过1.5倍。 ([链接](http://perfjs.info/#!/F33A9807-6D63-4773-AF70-7DA57E79A90C)) - Pencroff
10个回答

51

在ECMAScript中,字符串连接速度更快。这是我创建的一个基准测试,向您展示:

http://jsben.ch/#/OJ3vo


1
更新:我发现了一些重要的事情,1)我们在join示例中不必要地重新创建数组,2)最好存储数组长度以防止在每次迭代时检查长度。 - ajax333221
11
“我们在join示例中不必要地重新创建了数组” 创建数组以便加入它是整个重点。 你更新后的jsperf比较的是苹果和橙子。如果您已经有一个数组,则join会更快。但人们比较的是仅为加入而创建一个数组与使用字符串连接。完全不同的情况。 - T.J. Crowder
4
"苹果对苹果": 连接不同长度的字符串2000次,可以使用数组逐步构建并使用 join 方法,也可以使用字符串拼接方法。在现代引擎中,使用字符串拼接方法的性能更好,且一直以来更易读/易于维护/易于调试。10年前我尝试过使用数组,当时它的性能略优于字符串拼接方法,但现在已经不是这样了。 - T.J. Crowder
1
我认为jsben.ch网站可能有问题。它的结果与jsperf.com不一致:https://dev59.com/xlcP5IYBdhLWcg3wTIMt - Venryx
1
2018年,FF v59,提到链接的结果 -> 数组连接(最快!) - Mehdi Dehghani
显示剩余10条评论

11
从2011年一直到现代,......请看下面使用字符串拼接的“join”重写以及它比标准实现慢多少。
// Number of times the standard `join` is faster, by Node.js versions:
// 0.10.44: ~2.0
// 0.11.16: ~4.6
// 0.12.13: ~4.7
// 4.4.4: ~4.66
// 5.11.0: ~4.75
// 6.1.0: Negative ~1.2 (something is wrong with 6.x at the moment)
function join(sep) {
    var res = '';
    if (this.length) {
        res += this[0];
        for (var i = 1; i < this.length; i++) {
            res += sep + this[i];
        }
    }
    return res;
}

教训是 - 不要手动拼接字符串,始终使用标准的join函数。


6
我遇到了这个话题,其他答案可能在2011年是正确的,但此时此刻加入确实更好。 - Cageman

9

我可以明确地说,使用Array.join()更快。我曾经处理过几段JavaScript代码,并通过放弃字符串操作而选择数组操作显著提高了性能。


7

2021年测试

请查看以下代码。结果:

在常规使用中,Firefox 中 push+join 比字符串连接慢80%。

在常规使用中,Chrome 中 push+join 比字符串连接慢140%。

function test(items = 100, rep = 1000000) {
  let str

  console.time('concat')
  for (let r = 0; r < rep; r++) {
    str = ''
    for (let i = 0; i < items; i++) {
      str += i
    }
  }
  console.timeEnd('concat')

  console.time('push+join')
  for (let r = 0; r < rep; r++) {
    const arr = []
    for (let i = 0; i < items; i++) {
      arr.push(i)
    }
    str = arr.join('')
  }
  console.timeEnd('push+join')
}

2
+1 更新答案,但当我回顾10年前我曾经担心过性能问题时,我感到非常不安,现在一切都关乎代码维护。 - ajax333221
嗨 @ajax333221,你让我这个初学者感到震惊,我一直以为维护只是关于性能的问题 :) - Ayman Morsy
虽然这并没有太大的改变,但你的代码也将数字转换为字符串,而这个操作也需要一些时间。 - NtsDK
虽然它没有太大的变化,但你的代码也将数字转换为字符串,这个操作也需要一些时间。 - undefined
@NtsDK 我猜是这样,但是在这两种情况下,每个整数都应该被转换相同次数,所以这是一个恒定的偏移量。如果有什么不同的话,它可能会使速度比例更加极端。 - Tobia

7

join在字符串数组已存在的情况下速度更快。真正的比较应该是:

  1. 将元素推入数组,然后将它们连接起来构建字符串
  2. 每次都不使用数组进行字符串拼接

对于迭代和字符串数量很少的情况下,无论您使用推送和连接还是直接字符串拼接都没有太大关系。但是,对于大量字符串,Chrome和Firefox中使用数组push和join似乎更快

这里是10到1000万个字符串的代码和测试结果:

Chrome:

strings 10
join-only: 0.01171875 ms
push-join: 0.137939453125 ms
concatenate: 0.01513671875 ms
strings 100
join-only: 0.01416015625 ms
push-join: 0.13427734375 ms
concatenate: 0.0830078125 ms
strings 1000
join-only: 0.048095703125 ms
push-join: 0.47216796875 ms
concatenate: 0.5517578125 ms
strings 10000
join-only: 0.465087890625 ms
push-join: 5.47314453125 ms
concatenate: 4.9619140625 ms
strings 100000
join-only: 7.6240234375 ms
push-join: 57.37109375 ms
concatenate: 67.028076171875 ms
strings 1000000
join-only: 67.666259765625 ms
push-join: 319.3837890625 ms
concatenate: 609.8369140625 ms
strings 10000000
join-only: 824.260009765625 ms
push-join: 3207.129150390625 ms
concatenate: 5959.56689453125 ms

Firefox:

strings 10
join-only: 0ms
push-join: 1ms
concatenate: 0ms
strings 100
join-only: 0ms
push-join: 0ms
concatenate: 0ms
strings 1000
join-only: 0ms
push-join: 1ms
concatenate: 0ms
strings 10000
join-only: 1ms
push-join: 2ms
concatenate: 0ms
strings 100000
join-only: 5ms
push-join: 11ms
concatenate: 8ms
strings 1000000
join-only: 39ms
push-join: 88ms
concatenate: 98ms
strings 10000000
join-only: 612ms
push-join: 1095ms
concatenate: 3249ms

测试代码:

for (var n = 10; n <= 10000000; n*=10) {
    
    var iterations = n;

    console.log("strings", iterations);
    console.time("push-join");
    arr = [];
    for (var i = 0; i< iterations; i++) {
        arr.push("a b c d e f g h i j k l m");
    }
    console.time("join-only");
    content = arr.join(",");
    console.timeEnd("join-only");
    console.timeEnd("push-join");

    content = "";

    console.time("concatenate");    
    for (var i = 0; i< iterations; i++) {
        content += "a b c d e f g h i j k l m";
    }
    console.timeEnd("concatenate");

}

4

2
根据名为“优化JavaScript代码”的此Google文档,字符串拼接比数组连接慢,但显然对于现代JavaScript引擎来说并非如此。
我为文档中使用的斐波那契测试示例制作了一个基准测试,结果显示拼接字符串比使用Array join快近4倍。

2
基准测试并不是很好,因为你不仅要将字符串连接与数组连接进行比较,而且在连接的情况下还要在基准测试中创建一个新数组。 - dpr

1

手动连接更快,适用于固定长度的数字数组。

这是一个JSPerf测试,测试这两个操作

zxy.join('/')

// versus

zxy[0] + '/' + zxy[1] + '/' + zxy[2]

// given the array

zxy = [1, 2, 3]

// resulting in the string '0/1/2'

结果:使用 Chrome 64.0.3282.186,Array.join 的速度慢了46%。


现在使用Chrome 65.0.3325.181版本,Array.join的速度变慢了71%。 - Matthias

1
我认为这不仅是性能问题,还涉及到内存问题。
由于字符串是不可变的,这意味着每次将一个字符串连接起来时,都会在内存中创建一个额外的字符串。但是数组是可变的,也就是说它们会保持相同的内存地址。
当然,这也取决于编程语言,但总的来说,使用数组是更好的解决方案。

-2

扩展运算符,用三个连续的点(...)编写,是ES6中的新功能,它使您能够将可迭代对象扩展或展开为多个元素。

const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"];
console.log(...books);

打印输出:Don Quixote、The Hobbit、Alice in Wonderland、Tale of Two Cities


1
只有当您的函数接受多个(...rest)参数时,此方法才有效。 console.log 就是这样一个例子。然而,这并不总是回答 OP 的问题,因为您可能正在使用仅接受 1 个字符串参数的函数,在这种情况下,展开运算符将失败。 - chharvey

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