JavaScript は不変文字列と可変文字列のどちらを使用しますか? 「文字列ビルダー」は必要ですか?
ベストアンサー1
これらは不変です。 のような方法で文字列内の文字を変更することはできませんvar myString = "abbdef"; myString[2] = 'c'
。 のような文字列操作メソッドは、trim
、slice
新しい文字列を返します。
同様に、同じ文字列への参照が2つある場合、一方を変更してももう一方には影響しません。
let a = b = "hello";
a = a + " world";
// b is not affected
神話の解明 - 文字列の連結は遅くない
私はいつも、Ash が回答で言及していたこと (Array.join を使用すると連結が高速になる) を聞いていたので、文字列を連結するさまざまな方法と、最も高速な方法を StringBuilder に抽象化する方法をテストしたいと考えました。これが真実かどうかを確認するために、いくつかのテストを書きました (真実ではありません)。
これは、プッシュを回避し、配列を使用して文字列を保存し、最後にそれらを結合する、最も速い方法であると信じていました。
class StringBuilderArrayIndex {
array = [];
index = 0;
append(str) {
this.array[this.index++] = str
}
toString() {
return this.array.join('')
}
}
いくつかのベンチマーク
- 以下のスニペットのテストケースを読んでください
- スニペットを実行する
- ベンチマークボタンを押してテストを実行し、結果を確認します
私は2種類のテストを作成しました
- 配列インデックスを使用して回避し
Array.push
、Array.join
- 直線的な文字列の連結
これらのテストごとに、定数値とランダムな文字列を追加してループしました。
<script benchmark>
// Number of times to loop through, appending random chars
const APPEND_COUNT = 1000;
const STR = 'Hot diggity dizzle';
function generateRandomString() {
const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const length = Math.floor(Math.random() * 10) + 1; // Random length between 1 and 10
let result = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
result += characters.charAt(randomIndex);
}
return result;
}
const randomStrings = Array.from({length: APPEND_COUNT}, generateRandomString);
class StringBuilderStringAppend {
str = '';
append(str) {
this.str += str;
}
toString() {
return this.str;
}
}
class StringBuilderArrayIndex {
array = [];
index = 0;
append(str) {
this.array[this.index] = str;
this.index++;
}
toString() {
return this.array.join('');
}
}
// @group Same string 'Hot diggity dizzle'
// @benchmark array push & join
{
const sb = new StringBuilderArrayIndex();
for (let i = 0; i < APPEND_COUNT; i++) {
sb.append(STR)
}
sb.toString();
}
// @benchmark string concatenation
{
const sb = new StringBuilderStringAppend();
for (let i = 0; i < APPEND_COUNT; i++) {
sb.append(STR)
}
sb.toString();
}
// @group Random strings
// @benchmark array push & join
{
const sb = new StringBuilderArrayIndex();
for (let i = 0; i < APPEND_COUNT; i++) {
sb.append(randomStrings[i])
}
sb.toString();
}
// @benchmark string concatenation
{
const sb = new StringBuilderStringAppend();
for (let i = 0; i < APPEND_COUNT; i++) {
sb.append(randomStrings[i])
}
sb.toString();
}
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
調査結果
現在、すべての最新ブラウザは文字列の連結をより適切に、少なくとも 2 倍の速度で処理します。
i-12600k (Alexander Nenashev 氏によって追加)
クローム/117
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x100000 224 232 254 266 275
array push & join 3.2x | x100000 722 753 757 762 763
Random strings
string concatenation 1.0x | x100000 261 268 270 273 279
array push & join 5.4x | x10000 142 147 148 155 166
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark
ファイアフォックス/118
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x100000 304 335 353 358 370
array push & join 9.5x | x10000 289 300 301 306 309
Random strings
string concatenation 1.0x | x100000 334 337 345 349 377
array push & join 5.1x | x10000 169 176 176 176 180
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark
2023年10月の2.4GHz 8コアi9 Macでの結果は以下の通りです。
クロム
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x100000 574 592 594 607 613
array push & join 2.7x | x10000 156 157 159 164 165
Random strings
string concatenation 1.0x | x100000 657 663 669 675 680
array push & join 4.3x | x10000 283 285 295 298 311
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark
ファイアフォックス
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x100000 546 648 659 663 677
array push & join 5.8x | x10000 314 320 326 331 335
Random strings
string concatenation 1.0x | x100000 647 739 764 765 804
array push & join 2.9x | x10000 187 188 199 219 231
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark
勇敢な
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x100000 566 571 572 579 600
array push & join 2.5x | x10000 144 145 159 162 166
Random strings
string concatenation 1.0x | x100000 649 658 659 663 669
array push & join 4.4x | x10000 285 285 290 292 300
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark `
サファリ
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x10000 76 77 77 79 82
array push & join 2.2x | x10000 168 168 174 178 186
Random strings
string concatenation 1.0x | x100000 878 884 889 892 903
array push & join 2.3x | x10000 199 200 202 202 204
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark `
オペラ
--------------------------------------------------------------------
Same string 'Hot diggity dizzle'
string concatenation 1.0x | x100000 577 579 581 584 608
array push & join 2.7x | x10000 157 162 165 166 171
Random strings
string concatenation 1.0x | x100000 688 694 740 750 781
array push & join 4.2x | x10000 291 315 316 317 379
--------------------------------------------------------------------
https://github.com/silentmantra/benchmark