javascript使用不可变字符串还是可变字符串?我需要一个“字符串生成器”吗?
当前回答
只是为了澄清像我这样头脑简单的人(来自MDN):
不可变对象是一旦对象被创建,其状态就不能改变的对象。 字符串和数字是不可变的。
不可变意味着:
你可以让一个变量名指向一个新的值,但是之前的值仍然保存在内存中。因此需要垃圾收集。 var immutableString = "Hello"; //在上面的代码中,创建了一个string值的新对象。 immutableString = immutableString + "World"; //我们现在将"World"附加到现有值。
这看起来像是我们在改变字符串'immutableString',但我们没有。而不是:
在给"immutableString"附加一个字符串值时,会发生以下事件: 检索"immutableString"的现有值 "World"被附加到"immutableString"的现有值 然后将结果值分配给一个新的内存块 "immutableString"对象现在指向新创建的内存空间 以前创建的内存空间现在可用于垃圾收集。
其他回答
来自犀牛的书:
In JavaScript, strings are immutable objects, which means that the characters within them may not be changed and that any operations on strings actually create new strings. Strings are assigned by reference, not by value. In general, when an object is assigned by reference, a change made to the object through one reference will be visible through all other references to the object. Because strings cannot be changed, however, you can have multiple references to a string object and not worry that the string value will change without your knowing it
它们是不可变的。你不能用像var myString = "abbdef"这样的方法来改变字符串中的字符;myString[2] = 'c'。字符串操作方法,如修剪,切片返回新字符串。
同样地,如果对同一个字符串有两个引用,修改其中一个不会影响另一个
let a = b = "hello";
a = a + " world";
// b is not affected
然而,我总是听到Ash在他的回答中提到的(使用Array。所以我想测试连接字符串的不同方法,并将最快的方法抽象到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('');
}
这里是性能速度测试。这三个都创造了一个巨大的字符串,由“你好,diggity dog”10万次连接到一个空字符串组成。
我创建了三种类型的测试
使用数组。push和Array.join 使用数组索引来避免数组。push,然后使用Array.join 直串连接
然后我通过将它们抽象为StringBuilderConcat, StringBuilderArrayPush和StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5创建了相同的三个测试,请去那里运行测试,这样我们就可以得到一个很好的示例。请注意,我修复了一个小错误,因此测试数据被擦除,一旦有足够的性能数据,我将更新表。访问http://jsperf.com/string-concat-without-sringbuilder/5查看旧的数据表。
以下是一些数字(Ma5rch 2018最新更新),如果你不想关注链接。每次测试的数值为每秒1000次操作(越高越好)
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 |
发现
现在,所有的常青树浏览器都能很好地处理字符串连接。数组中。join只支持IE 11 总的来说,Opera是最快的,是Array.join的4倍 其次是Firefox和Array。连接只是稍微慢在FF但相当慢(3倍)在Chrome。 Chrome排名第三,但string concat比Array.join快3倍 创建一个StringBuilder似乎对性能影响不大。
希望其他人会觉得这个有用
不同的测试用例
因为@RoyTinker认为我的测试是有缺陷的,我创建了一个新的情况下,不创建一个大字符串连接相同的字符串,它使用不同的字符为每次迭代。字符串连接似乎还是更快,或者一样快。让我们进行测试
我建议每个人都应该继续考虑其他测试方法,并在下面添加到不同测试用例的新链接。
http://jsperf.com/string-concat-without-sringbuilder/7
Javascript中的字符串是不可变的
性能提示:
如果必须连接大字符串,请将字符串部分放入数组中,并使用array . join()方法获取整个字符串。这对于连接大量字符串来说可以快很多倍。
JavaScript中没有StringBuilder。
只是为了澄清像我这样头脑简单的人(来自MDN):
不可变对象是一旦对象被创建,其状态就不能改变的对象。 字符串和数字是不可变的。
不可变意味着:
你可以让一个变量名指向一个新的值,但是之前的值仍然保存在内存中。因此需要垃圾收集。 var immutableString = "Hello"; //在上面的代码中,创建了一个string值的新对象。 immutableString = immutableString + "World"; //我们现在将"World"附加到现有值。
这看起来像是我们在改变字符串'immutableString',但我们没有。而不是:
在给"immutableString"附加一个字符串值时,会发生以下事件: 检索"immutableString"的现有值 "World"被附加到"immutableString"的现有值 然后将结果值分配给一个新的内存块 "immutableString"对象现在指向新创建的内存空间 以前创建的内存空间现在可用于垃圾收集。