JavaScriptには組み込みのstringbuilderクラスがありますか?


回答:


318

Internet Explorer用のコードを記述する必要がある場合は、配列結合を使用する実装を選択したことを確認してください。文字列を+or +=演算子で連結すると、IEでは非常に遅くなります。これは特にIE6に当てはまります。最近のブラウザで+=は、通常、配列の結合と同じくらい高速です。

多くの文字列連結を行う必要がある場合、通常は配列を埋め、文字列ビルダークラスを使用しません。

var html = [];
html.push(
  "<html>",
  "<body>",
  "bla bla bla",
  "</body>",
  "</html>"
);
return html.join("");

pushメソッドは複数の引数を受け入れることに注意してください。


7
また、出力をインラインで生成する場合、またはすべてのメンバーがリテラルである[foo(), "bar", "baz"].join("");場合も機能します。
匿名の

1
Dropboxリンクがほぼ3年間機能し続けるとは思えないかもしれませんが、比較について知りたいと思います。
Cornelius

1
@DaveWard、リンクが壊れています:(
Ivan Kochurkin '28

文字列+文字列+文字列
Andrew Ehrlich

12
push複数の引数を受け入れることができることを知りませんでした。ランダムに学ぶこと。
2016年

55

http://jsperf.com/javascript-concat-vs-join/2でパフォーマンスを再確認しました。テストケースはアルファベットを1,000回連結または結合します。

現在のブラウザ(FF、Opera、IE11、Chrome)では、「連結」は「結合」よりも約4〜10倍高速です。

IE8では、どちらもほぼ同じ結果を返します。

IE7では、 "join"は残念ながら約100倍高速です。


3
これをありがとう。これは回答リストに追加する必要があります。また、IE10の方がはるかに高速です(これは最新のブラウザーではないことはわかっていますが、NMCI開発者がこれを目にする可能性がある場合はそれについて言及します)。
James Wilson

@Andreas文字列が読み取られないため、テストがChromeのコードパスに到達し、実際の連結が行われないと思います。ただし、それを強制した場合でも、実行速度はかなり速くなります:jsperf.com/yet-another-string-concat-test/1
Joseph Lennox

37

いいえ、文字列を構築するための組み込みサポートはありません。代わりに連結を使用する必要があります。

もちろん、文字列のさまざまな部分の配列を作成し、その配列を呼び出すjoin()こともできますが、その場合、使用しているJavaScriptインタープリターでの結合の実装方法によって異なります。

str1+str2メソッドの速度とメソッドの速度を比較する実験を行いましたarray.push(str1, str2).join()。コードはシンプルでした:

var iIterations =800000;
var d1 = (new Date()).valueOf();
str1 = "";
for (var i = 0; i<iIterations; i++)
    str1 = str1 + Math.random().toString();
var d2 = (new Date()).valueOf();
log("Time (strings): " + (d2-d1));

var d3 = (new Date()).valueOf();
arr1 = [];
for (var i = 0; i<iIterations; i++)
    arr1.push(Math.random().toString());
var str2 = arr1.join("");
var d4 = (new Date()).valueOf();
log("Time (arrays): " + (d4-d3));

Windows 7 x64上のInternet Explorer 8とFirefox 3.5.5でテストしました。

最初は、少数の反復(数百、数千項目)でテストしました。結果は予測できませんでした(文字列の連結に0ミリ秒かかる場合があり、16ミリ秒かかることもありました。これは、配列の結合にも同じです)。

カウントを50,000に増やしたとき、結果はブラウザーによって異なりました-Internet Explorerでは、文字列の連結はより速く(94ミリ秒)、結合はより遅く(125ミリ秒)、Firefoxでは配列の結合はより高速(113ミリ秒)でした。文字列結合(117ミリ秒)。

次に、カウントを500'000に増やしました。現在、両方のブラウザで文字列の連結よりも低速array.join()でした。文字列の連結は、Internet Explorerで937ミリ秒、Firefoxで1155ミリ秒、Internet Explorerで配列結合1265ミリ秒、Firefoxで1207ミリ秒でした。

「スクリプトの実行に時間がかかりすぎる」ことなくInternet Explorerでテストできる最大反復回数は850,000でした。次に、Internet Explorerは文字列連結で1593、配列結合で2046、Firefoxでは文字列連結で2101、配列結合で2249でした。

結果 -反復回数が少ない場合はarray.join()、Firefoxの方が高速になる可能性があるため、を使用してみてください。数が増えると、string1+string2メソッドは速くなります。

更新

テストはInternet Explorer 6(Windows XP)で行いました。100,000回を超える反復でテストを試行した場合、プロセスはすぐに応答を停止し、終了しませんでした。40,000回の反復で、結果は

Time (strings): 59175 ms
Time (arrays): 220 ms

つまり、Internet Explorer 6をサポートする必要がある場合array.join()は、文字列の連結よりも高速な方法を選択してください。


join()ECMAScriptの一部であり、すべてのJavaScriptインタープリターがそれを実装しています。なぜ「依存する」のでしょうか?
イーライグレイ

彼はそれがどのように実装されたかを意味します...ループで一度に作成されるのではなく、文字列が継続的に追加されるように実装されている場合、結合を使用しても意味がありません
John

はい、それは私が実際に意味したことでした。私の英語を許してください;-) 2つのブラウザでどの方法が動作するかを比較した結果を追加しました。ご覧のとおり、違います。
ナイービスト、2010年

2
IE6はいつものように例外です:)
Gordon Tucker

10
IE6を使用している人は、すべてが本当に遅いことに慣れています。彼らがあなたを責めるとは思わない。
Lodewijk

8

このコードは、いくつかの変更を加えて、実行したいルートのように見えます。

追加メソッドを次のように変更する必要があります。数値0を受け入れるように変更し、それを返すthisようにして、アペンドをチェーンできるようにしました。

StringBuilder.prototype.append = function (value) {
    if (value || value === 0) {
        this.strings.push(value);
    }
    return this;
}

NaN以外の数値と空でない文字列のみを受け入れるのはなぜですか?あなたの方法は受け付けませんnullfalse空の文字列、、 undefined、またはNaN
イーライグレイ、

@Elijah-有効な文字列と数値以外は何も受け入れないことで、StringBuilderクラスをクリーンに保つことを好みます。それは単なる個人的な好みです。
Gordon Tucker

5

JavaScriptのECMAScript 6バージョン(別名ECMAScript 2015)では、文字列リテラルが導入されました。

var classType = "stringbuilder";
var q = `Does JavaScript have a built-in ${classType} class?`;

文字列が単一引用符ではなくバックティックで囲まれていることに注意してください。


17
これはどのように質問に答えますか?
Peter Mortensen

@ピーター・モーテンセン、この答えは文字列を構築する別の方法を提供するだけです。元の投稿者は、求められている文字列ビルダー機能のタイプを特定していませんでした。
Theophilus

1
これは質問の答えにはなりません。全然。
Massimiliano Kraus

3

C#では次のようなことができます

 String.Format("hello {0}, your age is {1}.",  "John",  29) 

JavaScriptでは次のようなことができます

 var x = "hello {0}, your age is {1}";
 x = x.replace(/\{0\}/g, "John");
 x = x.replace(/\{1\}/g, 29);

2
文字列結合の代わりに正規表現を実行すると、パフォーマンスが向上することを強く疑います
tic

さらに、これはひどい実装です。{0}置換後の文字列にが含まれていると壊れます{1}
池上

@ikegami文字列は変数ではなく定数なので、アプリオリに何が含まれているかがわかります。
スポーツ

@sports、それらすべてをコード全体にコピーして貼り付けることは、さらに悪い考えです。
池上

非キャプチャグループを置き換える$ 1および$ 2の1つのライナー:x..replace(/([\ s \ S] *?)\ {0 \}([\ s \ S] *?)\ {1 \} / g、 "$ 1Tom $ 225")
T.CK

1

興味のある方のために、Array.joinを呼び出す代わりの方法を次に示します。

var arrayOfStrings = ['foo', 'bar'];
var result = String.concat.apply(null, arrayOfStrings);
console.log(result);

予想通り、出力は文字列「foobar」です。Firefoxでは、このアプローチはArray.joinよりも優れていますが、連結によって+より優れています。String.concatでは各セグメントを個別の引数として指定する必要があるため、呼び出し元は、実行中のJavaScriptエンジンによって課される引数カウント制限によって制限されます。見てみましょうFunction.prototype.applyの()のドキュメント詳細については、を。


「String.concat」が定義されていないため、これはChromeでは失敗します。代わりに、 ''。concat.apply( ''、arrayOfStrings)を使用できます。しかし、これはまだ非常に遅い方法です。
Andreas

1

私はこの関数を定義しました:

function format() {
        var args = arguments;
        if (args.length <= 1) { 
            return args;
        }
        var result = args[0];
        for (var i = 1; i < args.length; i++) {
            result = result.replace(new RegExp("\\{" + (i - 1) + "\\}", "g"), args[i]);
        }
        return result;
    }

そしてc#のように呼び出すことができます:

 var text = format("hello {0}, your age is {1}.",  "John",  29);

結果:

こんにちはジョン、あなたの年齢は29歳です。


1
私はそれが好きです... c#のように見えます
Ayo Adesina

2
この答えは質問とは関係ありません。
Massimiliano Kraus

0

JavaScriptで多くの文字列連結を実行していることに気付いたとき、私はテンプレートを探し始めます。Handlebars.jsは、HTMLとJavaScriptをより読みやすく維持して、非常にうまく機能します。http://handlebarsjs.com


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.