如何在JavaScript里拼接字符串?

2022-01-06大约11分钟

如果你有Java或其他语言的编程经验,那么可能会疑惑,在JavaScript里,没有StringBuilder之类的类或对象可以用,那么如何拼接字符串才是高效的呢?

一般来讲,JavaScript里拼接字符串有4种方式:

1. 使用+运算符来拼接

这种方式比较常见,用+将字符串连起来,得到一个新的字符串。

const s1 = "Hello";
const s2 = "乐码范!";
const result = s1 + " " + s2;
console.log(result); // Hello 乐码范! Again!

这种方法,可能许多编程老手会说有性能问题,理由是字符串是不可变的,因此每次拼接操作都会重新创建一个新的字符串。在每一次拼接大量字符串的时候,都会产生内存申请及回收操作,当字符串很长的时候,会很耗内存,导致代码性能很低。

其实,这在JavaScript里是个老观念了,因为现代的JavaScript引擎已经对这种场景做了优化,性能不再是一个问题。稍后我们再来看性能比较。

这种方式在JavaScript里不推荐用,不是因为性能问题,而是和模版字符串相比,代码不直观。

2. 使用concat()方法

string对象有个concat()方法可以用来拼接字符串:

const s1 = "Hello";
const s2 = "乐码范!";
const result = s1.concat(" ", s2);
console.log(result); // Hello 乐码范!

3. 使用Array.join()方法

JavaScript里的数组有个join()方法,可以将数组里面的字符串合成一个字符串。

const result = ["Hello", "乐码范!"].join(" ");
console.log(result); // Hello 乐码范!

这种方法可以用来做大量字符串的合并,是传统上性能比较高的方法。

4. 使用模版字符串(Template literals)

在ES5里面,JavaScript引入了一个新的叫做模版字符串的语法,使用反引号```来格式化一个字符串。

const s1 = "Hello";
const s2 = "乐码范!";
const result = `${s1} ${s2}`;
console.log(result); // Hello 乐码范!

上面的代码和第一种使用+号的方式来比,我们很容易看出最终字符串result的结构,因此更容易读。关于模版字符串的语法,可以参考MDN

比较一下性能

由于模版字符串主要用于拼接数量有限的几个变量,所以在拼接大量字符串的时候,我们不会用它。所以这里只是比较一下前三种的性能(下面的代码可以拷贝到您的本地运行):

const s1 = "Hello 乐码范!";

const count = 1000000;

// 生成测试数据
const data = [];
for (let i = 0; i < count; i++) {
    data.push(s1 + i);
}

console.time('加号拼接')
let result = '';
for (let i = 0; i < count; i++) {
    result = result + data[i];
}
console.timeEnd('加号拼接');

console.time('concat()拼接')
result = '';
for (let i = 0; i < count; i++) {
    result = result.concat(data[i]);
}
console.timeEnd('concat()拼接');

console.time('Array.join()拼接')
result = '';
const values = [];
for (let i = 0; i < count; i++) {
    values.push(data[i]);
}
result = values.join();
console.timeEnd('Array.join()拼接');  

这个结果,在同一台电脑上,Node.js v14和Chrome浏览器里面跑的一次结果是这样的:

拼接方式 Node.js V14 (毫秒) Chrome V92 (毫秒)
加号拼接 121.78 92.64
concat()拼接 116.99 67.44
Array.join()拼接 142.75 137.48

由此可以看出,三种方式concat()是最快的,但是三种方式的性能,不管是在Node.js还是Chrome浏览器上,实际是差不多的。虽有差异,但偶尔跑的结果顶多是一两倍的差异,而不是数量级上的差异。

因此,在实际写代码的时候,完全可以根据场景和习惯来使用,不用考虑上面不同的写法造成的性能上的差异。

注意
由于IE浏览器的性能很差,因此,上面的结论不适用于IE浏览器,仅适用于目前主流的浏览器和Node.js环境。