JavaScript 字符串是不可变的吗?我需要JavaScript中的“字符串生成器”吗?

2022-08-30 00:14:57

javascript使用不可变或可变字符串吗?我需要“字符串生成器”吗?


答案 1

它们是不可变的。不能使用类似 的内容更改字符串中的字符。字符串操作方法(如 trimslice)将返回新字符串。var myString = "abbdef"; myString[2] = 'c'

同样,如果您有两个对同一字符串的引用,则修改其中一个不会影响另一个

let a = b = "hello";
a = a + " world";
// b is not affected

但是,我总是听到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.pushArray.join
  • 使用数组索引来避免 ,然后使用Array.pushArray.join
  • 直弦串联

然后,我通过将它们抽象为 创建了相同的三个测试,并 http://jsperf.com/string-concat-without-sringbuilder/5 请去那里运行测试,以便我们可以得到一个很好的样本。请注意,我修复了一个小错误,因此测试的数据被擦除了,一旦有足够的性能数据,我将更新表。转到旧数据表的 http://jsperf.com/string-concat-without-sringbuilder/5StringBuilderConcatStringBuilderArrayPushStringBuilderArrayIndex

以下是一些数字(Ma5rch 2018中的最新更新),如果您不想点击该链接。每个测试的数字以 1000 次操作/秒为单位(越高越好)

浏览器 指数 康卡特 SBIndex SBPush SBConcat
铬 71.0.3578 988 1006 2902 963 1008 2902
火狐 65 1979 1902 2197 1917 1873 1953
边缘 593 373 952 361 415 444
爆炸物 11 655 532 761 537 567 387
歌剧 58.0.3135 1135 1200 4357 1137 1188 4294

发现

  • 如今,所有常青浏览器都能很好地处理字符串连接。 只帮助IE 11Array.join

  • 总体而言,Opera速度最快,是Array.join的4倍。

  • Firefox排在第二位,在FF中仅略慢,但在Chrome中则相当慢(3倍)。Array.join

  • Chrome 排名第三,但 string concat 比 Array.join 快 3 倍

  • 创建一个 StringBuilder 似乎不会对性能产生太大影响。

希望其他人发现这很有用

不同的测试用例

由于@RoyTinker认为我的测试有缺陷,因此我创建了一个新案例,该案例不会通过连接同一字符串来创建大字符串,而是在每次迭代中使用不同的字符。字符串串联似乎仍然更快或一样快。让我们运行这些测试。

我建议每个人都应该继续考虑其他方法来测试这一点,并随时在下面的不同测试用例中添加新链接。

http://jsperf.com/string-concat-without-sringbuilder/7


答案 2

来自犀牛书

在JavaScript中,字符串是不可变的对象,这意味着其中的字符可能不会被更改,并且对字符串的任何操作实际上都会创建新字符串。字符串是按引用分配的,而不是按值分配的。通常,当按引用分配对象时,通过一个引用对对象所做的更改将通过对该对象的所有其他引用可见。但是,由于字符串无法更改,因此您可以对字符串对象进行多个引用,而不必担心字符串值会在您不知情的情况下更改