Dev*_*ris 223 javascript string
javascript使用不可变或可变的字符串吗?我需要一个"字符串构建器"吗?
Jua*_*des 281
他们是不变的.您无法使用类似的内容更改字符串中的字符var myString = "abbdef"; myString[2] = 'c'.该字符串操作方法,例如trim,slice返回新的字符串.
同样,如果您对同一个字符串有两个引用,则修改一个字符串不会影响另一个字符串
let a = b = "hello";
a = a + " world";
// b is not affected
Run Code Online (Sandbox Code Playgroud)
但是,我总是听到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('');
}
Run Code Online (Sandbox Code Playgroud)
这是性能速度测试.他们三个都创造了一个巨大的字符串,由"Hello diggity dog"一串空串连接十万次组成.
我创建了三种类型的测试
Array.push和Array.joinArray.push,然后使用Array.join然后我通过抽象它们创建了相同的三个测试StringBuilderConcat,StringBuilderArrayPush并且StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5请去那里运行测试,这样我们就可以得到一个很好的样本.请注意,我修复了一个小错误,因此测试数据被擦除,一旦有足够的性能数据,我将更新表.转到旧数据表的http://jsperf.com/string-concat-without-sringbuilder/5.
如果您不想关注该链接,请参阅2013年2月21日的部分数据.每次测试的数量都在运行/秒(越高越好)
| Browser | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 71.0.3578 | 988 | 1006 | 2902 | 963 | 1008 | 2902 |
| Firefox 65 | 1979 | 1902 | 2197 | 1917 | 1873 | 1953 |
| Edge | 593 | 373 | 952 | 361 | 415 | 444 |
| Exploder 11 | 655 | 532 | 761 | 537 | 567 | 387 |
| Opera 58.0.3135 | 1135 | 1200 | 4357 | 1137 | 1188 | 4294 |
Run Code Online (Sandbox Code Playgroud)
发现
如今,所有浏览器都能很好地处理字符串连接.Array.join只能帮助Opera
总的来说,Chrome是最快的,在27.0中以1025 ops/sec为单位.比使用Array.join()快10倍
Firefox排在第二位,大约550次操作/秒(但20.0似乎已经退步).Array.join大约慢了4-5倍.
IE是最快的直接串连接,使用var myString = "abbdef"; myString[2] = 'c'和它真的很慢trim.IE 9 slice不会那么慢,并且所有SB抽象的执行方式几乎相同(可能是因为方法开销)
Opera是"Hello diggity dog"实际帮助的唯一一个,它的速度是字符串连接的2-3倍.
创建一个StringBuilder来抽象出每个浏览器的性能问题弊大于利.方法调用的开销可能是可以接受的,但趋势似乎是浏览器更聪明地处理字符串连接.只有你的目标受众是Opera才有意义,所以你可以在那里使用Array.join并在其他地方使用String连接(这意味着所有其他浏览器都受到了攻击)
希望别人觉得这很有用
不同的测试用例
由于@RoyTinker认为我的测试存在缺陷,因此我创建了一个新的案例,它不会通过连接相同的字符串来创建大字符串,它会为每次迭代使用不同的字符.字符串连接似乎仍然更快或更快.让我们让这些测试运行起来.
我建议每个人都应该考虑其他方法来测试这个,并随意添加新链接到下面的不同测试用例.
http://jsperf.com/string-concat-without-sringbuilder/7
min*_*nty 42
来自犀牛书:
在JavaScript中,字符串是不可变对象,这意味着它们中的字符可能不会被更改,并且对字符串的任何操作实际上都会创建新字符串.字符串按引用分配,而不是按值分配.通常,当通过引用分配对象时,通过一个引用对对象所做的更改将通过对该对象的所有其他引用可见.但是,由于无法更改字符串,因此您可以对字符串对象进行多次引用,而不必担心字符串值会在您不知情的情况下发生更改
Ash*_*Ash 20
表现提示:
如果必须连接大字符串,请将字符串部分放入数组中并使用该Array.Join()方法获取整个字符串.对于连接大量字符串,这可以快许多倍.
StringBuilderJavaScript中没有.
Kat*_*ink 15
只是为了澄清像我这样的简单头脑(来自MDN):
不可变对象是一旦创建对象其状态就无法更改的对象。
字符串和数字是不可变的。
不可变意味着:
您可以使变量名称指向一个新值,但先前的值仍保留在内存中。因此需要垃圾收集。
var immutableString = "Hello";// 在上面的代码中,创建了一个带有字符串值的新对象。
immutableString = immutableString + "World";// 我们现在将“World”附加到现有值。
这看起来我们正在改变字符串 'immutableString',但我们没有。反而:
将字符串值附加到“immutableString”后,会发生以下事件:
- 检索“immutableString”的现有值
- “World”附加到“immutableString”的现有值
- 然后将结果值分配给新的内存块
- “immutableString”对象现在指向新创建的内存空间
- 以前创建的内存空间现在可用于垃圾收集。
小智 5
字符串类型值是不可变的,但使用 String() 构造函数创建的 String 对象是可变的,因为它是一个对象,您可以向它添加新属性。
> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }
Run Code Online (Sandbox Code Playgroud)
同时,虽然您可以添加新属性,但无法更改已经存在的属性
综上所述,1.所有字符串类型值(原始类型)都是不可变的。2. String对象是可变的,但它包含的字符串类型值(原始类型)是不可变的。