273

JavaScriptは不変または可変の文字列を使用しますか? 「文字列ビルダー」が必要ですか?

4

10 に答える 10

331

それらは不変です。のような文字列内の文字を変更することはできませんvar myString = "abbdef"; myString[2] = 'c'。などの文字列操作メソッドはtrimslice新しい文字列を返します。

同様に、同じ文字列への参照が 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 つのテストを に抽象化して作成し、StringBuilderConcathttp://jsperf.com/string-concat-without-sringbuilder/5アクセスしてテストを実行して、素敵なサンプルを入手してください。小さなバグを修正したため、テストのデータが消去されたことに注意してください。十分なパフォーマンス データが得られたら、表を更新します。古いデータ テーブルについては、http://jsperf.com/string-concat-without-sringbuilder/5にアクセスしてください。StringBuilderArrayPushStringBuilderArrayIndex

リンクをたどりたくない場合は、ここにいくつかの数値があります (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.joinIE 11のみを助けます

  • 全体的に、Opera が最速で、Array.join の 4 倍の速さです。

  • Firefox は 2 番目でArray.join、FF ではわずかに遅くなりますが、Chrome ではかなり遅くなります (3 倍)。

  • Chrome は 3 番目ですが、文字列連結は Array.join よりも 3 倍高速です

  • StringBuilder を作成しても、パフォーマンスにはあまり影響しないようです。

他の誰かがこれが役に立つことを願っています

別のテスト ケース

@RoyTinker は私のテストに欠陥があると考えたので、同じ文字列を連結して大きな文字列を作成しない新しいケースを作成しました。これは反復ごとに異なる文字を使用します。文字列の連結は、依然として高速であるか、または同等の速さであると思われました。これらのテストを実行しましょう。

これをテストする他の方法を考え続け、以下のさまざまなテスト ケースへの新しいリンクを自由に追加してください。

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

于 2011-01-17T21:03:35.843 に答える
44

サイの本から:

JavaScript では、文字列は不変オブジェクトです。つまり、文字列内の文字は変更できず、文字列に対する操作は実際に新しい文字列を作成します。文字列は、値ではなく参照によって割り当てられます。一般に、オブジェクトが参照によって割り当てられる場合、1 つの参照によってオブジェクトに加えられた変更は、そのオブジェクトへの他のすべての参照を通じて表示されます。ただし、文字列は変更できないため、文字列オブジェクトへの参照を複数持つことができ、知らないうちに文字列値が変更される心配はありません。

于 2008-09-09T03:51:12.723 に答える
23

パフォーマンスのヒント:

大きな文字列を連結する必要がある場合は、文字列部分を配列に入れ、Array.Join()メソッドを使用して文字列全体を取得します。これは、多数の文字列を連結する場合に何倍も高速になる可能性があります。

StringBuilderJavaScriptにはありません。

于 2008-09-09T03:55:55.880 に答える
1

ASP.NET Ajax の StringBuilder に関するあなたの質問 (Ash の回答へのコメント) に関して、専門家はこれについて意見が分かれているようです。

Christian Wenz は、彼の著書Programming ASP.NET AJAX (O'Reilly) で、「このアプローチはメモリに測定可能な影響を与えません (実際、実装は標準のアプローチよりも少し遅いようです)」と述べています。

一方、Gallo らは著書ASP.NET AJAX in Action (Manning) で、「連結する文字列の数が多い場合、文字列ビルダーはパフォーマンスの大幅な低下を避けるために不可欠なオブジェクトになります」と述べています。

独自のベンチマークを行う必要があり、ブラウザ間でも結果が異なる可能性があると思います。ただし、パフォーマンスが向上しない場合でも、C# や Java などの言語で StringBuilders を使用してコーディングすることに慣れているプログラマーにとっては、依然として「有用」であると見なされる場合があります。

于 2008-09-09T04:15:57.173 に答える
0

JavaScript 文字列は確かに不変です。

于 2008-09-09T03:50:05.177 に答える
-1

JavaScript の文字列は不変です

于 2008-09-09T03:50:51.303 に答える