如何更高效的拼接字符串?

技术博客 (171) 2023-11-25 09:01:01

最常用的连接字符串的方法应该是下面几种:

// 1.=操作符
str = 'a' + 'b' + 'c';
// 2. +=操作符
str = 'a';
str += 'b';
str += 'c';
// 3. Array.join()
str = ['a', 'b', 'c'].join('');
// 4. String.concat()
str = 'a';
str = str.concat('b', 'c');

那么来看一下这几种有什么区别,或者会造成什么影响。


= 和 +=操作符

运行str += 'one' + 'two'会经历以下4个过程:

  1. 在内存中创建一个临时字符串;
  2. 连接后的字符串onetwo被赋值给该临时字符串;
  3. 临时字符串与str当前的值连接;
  4. 结果赋值给str

拼接这个短短的字符串就会经历以上4个步骤,那么可以进行优化吗?请看下面的代码:

// 1
str += 'one';
str += 'two';
// 2
str = str + 'one' + 'two';

以上两种方式虽然能达到同样的效果,但是却可以避免产生临时字符串(也就是4个步骤中的1&2步骤);在大多数浏览器中这样做会提速10%~40%(IE7以上,IE8效果不明显,实现机制与此不同)。

但是如果将上面的代码2换成:str = 'one' + str + 'two',则优化将失效。这与浏览器合并字符串时分配内存的方法有关:

除IE外,其他浏览器会尝试为表达式左侧的字符串分配更多的内存,然后简单地将第二个字符串拷贝至它的末尾。如果在一个循环中,基础字符串位于最左端的位置,就可以避免重复拷贝一个逐渐变大的基础字符串。

基本字符串可以理解为连接时排在前面的字符串。也就是说:str + 'one'意味着拷贝one并附加在str之后,而'one' + str则意味着要拷贝str并附加在'one'之后,如果str很大,拷贝过程的性能损耗(内存占用)就会很高。

说回IE8的实现机制:

在IE8的实现中,连接字符串只是记录现有的字符串的引用来构造新的字符串。在最后时刻(当你真正要使用连接后的字符串时),字符串的各个部分才会逐个拷贝到一个新的“真正的”字符串中,然后用它取代先前的字符串引用,所以并非每次使用字符串时都发生合并操作。

而IE7的实现机制更糟糕:

每连接一对字符串都要把它复制到一块新分配的内存中。

Array.join() 和 String.prototype.concat()

大多数浏览器中,数组项合并比其他字符串连接方法更慢

Array.join()当把所有的数组的元素连接在一起时,浏览器会分配足够的内存来存放整个字符串,而且不会多次拷贝最终字符串中相同的部分。

字符串的原生方法concat()能接收任意数量的参数,并将每一个参数附加到所调用的字符串上。但是多数情况下,使用concat()比使用简单的++=稍慢,尤其在IE,Opera和Chrome中慢得更明显。


在《高性能JavaScript》看到了就记录一下,方便以后查看。

THE END

发表回复