JavaScriptは不変または可変の文字列を使用しますか? 「文字列ビルダー」が必要ですか?
10 に答える
それらは不変です。のような文字列内の文字を変更することはできませんvar myString = "abbdef"; myString[2] = 'c'
。などの文字列操作メソッドはtrim
、slice
新しい文字列を返します。
同様に、同じ文字列への参照が 2 つある場合、一方を変更しても他方には影響しません。
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"
これら 3 つすべてが、空の文字列に 10 万回連結された巨大な文字列を作成します。
3種類のテストを作成しました
Array.push
と_Array.join
- 配列インデックスを使用して回避
Array.push
し、次に使用するArray.join
- ストレート文字列連結
次に、同じ 3 つのテストを に抽象化して作成し、StringBuilderConcat
http://jsperf.com/string-concat-without-sringbuilder/5にアクセスしてテストを実行して、素敵なサンプルを入手してください。小さなバグを修正したため、テストのデータが消去されたことに注意してください。十分なパフォーマンス データが得られたら、表を更新します。古いデータ テーブルについては、http://jsperf.com/string-concat-without-sringbuilder/5にアクセスしてください。StringBuilderArrayPush
StringBuilderArrayIndex
リンクをたどりたくない場合は、ここにいくつかの数値があります (Ma5rch 2018 の最新更新)。各テストの数値は 1000 操作/秒です (高いほど良い) 。
ブラウザ | 索引 | 押す | 連結 | SBIndex | SBPush | SBConcat |
---|---|---|---|---|---|---|
クロム 71.0.3578 | 988 | 1006 | 2902 | 963 | 1008 | 2902 |
Firefox 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 |
所見
最近では、常緑のブラウザはすべて、文字列の連結を適切に処理します。
Array.join
IE 11のみを助けます全体的に、Opera が最速で、Array.join の 4 倍の速さです。
Firefox は 2 番目で
Array.join
、FF ではわずかに遅くなりますが、Chrome ではかなり遅くなります (3 倍)。Chrome は 3 番目ですが、文字列連結は Array.join よりも 3 倍高速です
StringBuilder を作成しても、パフォーマンスにはあまり影響しないようです。
他の誰かがこれが役に立つことを願っています
別のテスト ケース
@RoyTinker は私のテストに欠陥があると考えたので、同じ文字列を連結して大きな文字列を作成しない新しいケースを作成しました。これは反復ごとに異なる文字を使用します。文字列の連結は、依然として高速であるか、または同等の速さであると思われました。これらのテストを実行しましょう。
これをテストする他の方法を考え続け、以下のさまざまなテスト ケースへの新しいリンクを自由に追加してください。
サイの本から:
JavaScript では、文字列は不変オブジェクトです。つまり、文字列内の文字は変更できず、文字列に対する操作は実際に新しい文字列を作成します。文字列は、値ではなく参照によって割り当てられます。一般に、オブジェクトが参照によって割り当てられる場合、1 つの参照によってオブジェクトに加えられた変更は、そのオブジェクトへの他のすべての参照を通じて表示されます。ただし、文字列は変更できないため、文字列オブジェクトへの参照を複数持つことができ、知らないうちに文字列値が変更される心配はありません。
パフォーマンスのヒント:
大きな文字列を連結する必要がある場合は、文字列部分を配列に入れ、Array.Join()
メソッドを使用して文字列全体を取得します。これは、多数の文字列を連結する場合に何倍も高速になる可能性があります。
StringBuilder
JavaScriptにはありません。
ASP.NET Ajax の StringBuilder に関するあなたの質問 (Ash の回答へのコメント) に関して、専門家はこれについて意見が分かれているようです。
Christian Wenz は、彼の著書Programming ASP.NET AJAX (O'Reilly) で、「このアプローチはメモリに測定可能な影響を与えません (実際、実装は標準のアプローチよりも少し遅いようです)」と述べています。
一方、Gallo らは著書ASP.NET AJAX in Action (Manning) で、「連結する文字列の数が多い場合、文字列ビルダーはパフォーマンスの大幅な低下を避けるために不可欠なオブジェクトになります」と述べています。
独自のベンチマークを行う必要があり、ブラウザ間でも結果が異なる可能性があると思います。ただし、パフォーマンスが向上しない場合でも、C# や Java などの言語で StringBuilders を使用してコーディングすることに慣れているプログラマーにとっては、依然として「有用」であると見なされる場合があります。
JavaScript 文字列は確かに不変です。
JavaScript の文字列は不変です