javascript使用不可变字符串还是可变字符串?我需要一个“字符串生成器”吗?


当前回答

性能提示:

如果必须连接大字符串,请将字符串部分放入数组中,并使用array . join()方法获取整个字符串。这对于连接大量字符串来说可以快很多倍。

JavaScript中没有StringBuilder。

其他回答

它们是不可变的。你不能用像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字符串确实是不可变的。

Javascript中的字符串是不可变的

关于你的问题(在你对Ash的回复的评论中)关于ASP中的StringBuilder。NET Ajax专家们似乎不同意这一点。

Christian Wenz在他的书《编程ASP。NET AJAX (O'Reilly)说,“这种方法对内存没有任何可测量的影响(事实上,实现似乎比标准方法慢一点)。”

另一方面,Gallo等人在他们的书ASP。NET AJAX in Action (Manning),“当要连接的字符串数量较大时,字符串构建器就成为避免巨大性能下降的基本对象。”

我猜您需要自己进行基准测试,不同浏览器的测试结果也可能不同。然而,即使它不能提高性能,对于习惯于用c#或Java等语言编写StringBuilders的程序员来说,它仍然被认为是“有用的”。

string类型的值是不可变的,但是使用string()构造函数创建的string对象是可变的,因为它是一个对象,您可以向它添加新的属性。

> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }

同时,虽然您可以添加新的属性,但不能更改已经存在的属性

Chrome控制台测试的截图

总之, 1. 所有字符串类型值(基本类型)都是不可变的。 2. String对象是可变的,但它包含的字符串类型值(基本类型)是不可变的。