JavaScript字符串是不可变的吗? 我需要JavaScript中的“字符串生成器”吗?
JavaScript使用不可变或可变字符串吗? 我需要一个“字符串生成器”吗?
它们是不可改变的。 你不能用类似var myString = "abbdef"; myString[2] = 'c'
改变字符串中的字符var myString = "abbdef"; myString[2] = 'c'
var myString = "abbdef"; myString[2] = 'c'
。 诸如trim
, slice
类的字符串操作方法返回新的字符串。
然而,我总是听到Ash在他的回答中提到过(使用Array.join更快地进行串联),所以我想测试串联字符串和将最快的方式抽象成StringBuilder的不同方法。 我写了一些测试,看看这是否属实(不是!)。
这是我相信会是最快的方式,尽管我一直认为添加一个方法调用可能会让它变慢。
function StringBuilder() {
this._array = [];
this._index = 0;
}
StringBuilder.prototype.append = function (str) {
this._array[this._index] = str;
this._index++;
}
StringBuilder.prototype.toString = function () {
return this._array.join('');
}
这里是性能速度测试。 他们三个人创建了一个由十万次连接"Hello diggity dog"
组成的巨大字符串,成为一个空字符串。
我创建了三种类型的测试
Array.push
和Array.join
Array.push
,然后使用Array.join
然后,我通过将它们抽象为StringBuilderConcat
, StringBuilderArrayPush
和StringBuilderArrayIndex
创建了相同的三个测试。请到那里并运行测试,以便我们可以得到一个很好的示例。 请注意,我修复了一个小错误,因此测试的数据已被清除,一旦有足够的性能数据,我将更新表格。 旧数据表转到http://jsperf.com/string-concat-without-sringbuilder/5。
如果您不想关注链接,以下是2013年2月21日的一些数字。 每次测试中的数字都在运行/秒( 越高越好 )
| Browser | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 24.0.1312 | 83 | 87 | 702 | 69 | 87 | 165 |
| Chrome 25.0.1364 | 43 | 47 | 620 | 42 | 42 | 68 |
| Firefox 10.0.10 | 164 | 164 | 533 | 164 | 16 | 421 |
| Firefox 19.0 | 70 | 70 | 259 | 70 | 70 | 186 |
| Exploder 7.0 | 51 | 33 | 58 | 31 | 37 | 45 |
| Exploder 8.0 | 48 | 30 | 58 | 30 | 36 | 36 |
| Exploder 9.0 | 87 | 64 | 95 | 61 | 61 | 61 |
| Opera 12.14 | 125 | 154 | 66 | 106 | 137 | 63 |
发现
如今,所有浏览器都能很好地处理字符串连接。 Array.join
只能帮助Opera
总的来说,Chrome是最快的,在27.0的时钟频率为1025 ops / sec。 比使用Array.join()快10倍
Firefox排名第二,大约550 ops / sec(但20.0似乎已经回落)。 Array.join
大约慢了4-5倍。
IE使用直接字符串连接速度最快,使用Array.join
和Array.push
速度非常慢。 IE 9使Array.join
不那么慢,并且所有SB抽象执行几乎相同的方式(可能是因为方法开销)
Opera是Array.join
实际帮助的唯一一个,它是字符串连接速度的2-3倍。
创建一个StringBuilder来抽象掉每个浏览器的性能问题会带来更多的伤害而不是好处。 方法调用的开销可能是可以接受的,但趋势似乎是浏览器更巧妙地处理字符串连接。 如果你的目标受众是Opera,这只会是有意义的,所以你可以在那里使用Array.join,并在其他地方使用String concatenation(这意味着所有其他浏览器都会受到打击)
希望别人认为这有用
不同的测试案例
由于@RoyTinker认为我的测试存在缺陷,因此我创建了一个新的案例,它不会通过连接相同的字符串来创建大字符串,而是为每次迭代使用不同的字符。 字符串连接看起来更快或者更快。 让我们让这些测试运行。
我建议每个人都应该考虑用其他方式来测试这个,感谢Roy的投入。
http://jsperf.com/string-concat-without-sringbuilder/7
来自犀牛书:
在JavaScript中,字符串是不可变的对象,这意味着它们中的字符可能不会改变,并且对字符串的任何操作实际上都会创建新的字符串。 字符串按引用分配,而不是按值分配。 通常,当一个对象被引用分配时,通过一个引用对对象所做的更改将通过对该对象的所有其他引用而可见。 但是,由于字符串不能更改,因此可以有多个对字符串对象的引用,而不用担心字符串值会在您不知情的情况下更改
性能提示:
如果必须连接大字符串,请将字符串部分放入数组中,并使用Array.Join()
方法获取整个字符串。 连接大量字符串的速度可能快很多倍。
JavaScript中没有StringBuilder
。
上一篇: Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?