JavaScript 字符串合并 性能优化

612 阅读2分钟

String Concatenation

image.png

以上是连接字符串的方法,当连接少量字符串时,所有函数都很快。但是合并字符串的长度和数量增加之后,就开始有区别了。

Plus (+) and Plus-Equals (+=) Operators 加和加等于操作

现代浏览器(除了 IE),对此方法都优化得很好。

首先,看一个例子。

str += "one" + "two"

执行此代码,发生四个步骤:

  1. 内存中创建一个临时字符串
  2. 历史字符串被赋值为 "onetwo"
  3. 临时字符串与 str 进行连接
  4. 将连接结果赋予 str

我们可以把例子改成

str += "one"
str += "two"

例子中直接将内容附加在 str 上,避免了临时变量(步骤1和2),在大多数浏览器上这样可加快 10% ~ 40%

实际上也可用以下一行代码实现这样的性能提升:

str = str + "one" + "two"
// 等价于 str = ((str+"one")+"two")

以 str 为基础,从左到右追加字符串。

注意!如果改变连接顺序 str = "one" + str + "two",会失去优化效果。

这与浏览器合并字符串时分配内存的方法有关。除IE以外,浏览器尝试扩展表达式左端字符串的内存,然后简单地将第二个字符串拷贝到它的尾部。如果在一个循环中,基本字符串位于最左端,就可以避免多次复制一个越来越大的基本字符串。

Array Joining 数组联结

大多数浏览器上,数组联结比连接字符串的其他方法慢,但是在 IE7及更早版本,它却是连接大量字符串唯一高效的途径。

var str = "I'm a thirty-five character string.",
newStr = "",
appends = 5000;
while (appends--) {
    newStr += str;
}

以下是 IE7使用 += 连接字符串所用的时间

image.png

IE7 会在循环过程中反复地为越来越大的字符串拷贝和分配内存。结果是以平方关系递增的运行时间和内存消耗。

使用数组联结可解决这个问题

var str = "I'm a thirty-five character string.",
strs = [],
newStr,
appends = 5000;
while (appends--) {
    strs[strs.length] = str;
}
newStr = strs.join("");

image.png

当联结一个数组时,浏览器分配足够大的内存用于存放整个字符串,也不会超过一次地拷贝最终字符串的同一部分。避免了重复的内存分配和拷贝越来越大的字符串。

参考资料:《高性能 JavaScript 编程》