+演算子はStringBuffer.append()よりもパフォーマンスが低い


91

私のチームでは、通常、次のような文字列連結を行います。

var url = // some dynamically generated URL
var sb = new StringBuffer();
sb.append("<a href='").append(url).append("'>click here</a>");

明らかに、次の方がはるかに読みやすくなっています。

var url = // some dynamically generated URL
var sb = "<a href='" + url + "'>click here</a>";

しかし、JSの専門家は、+オペレーターのパフォーマンスはのものよりも低いと主張していStringBuffer.append()ます。これは本当ですか?


92
JavaScriptにはStringBufferはありません
Tomas

7
ドン、あなたはJavaについて言及していましたか?
James McMahon

私の経験では、[].join('')いくつかの本当にワイヤードな動作を示したので、+:-/
martyglaubitzに戻って感じ

1
ここでの基本的な質問は文字列の連結についてですが、このようなhtml要素を作成するときには注意が必要です。またはがurl含まれていると、例が壊れる可能性があります。'\n
スタイフル2013

回答:


46

Internet Explorerは、今日の世界でこれに本当に苦しんでいる唯一のブラウザーです。(バージョン5、6、および7は低速でした。8は同じ低下を示していません。)さらに、IEは文字列が長くなるほど遅くなります。

長い文字列を連結する場合は、必ずarray.joinテクニックを使用してください。(または、読みやすくするためにこれを囲むStringBufferラッパー。)しかし、文字列が短い場合は、気にしないでください。


102

パフォーマンスが大幅に異なる可能性は非常に低いため、この例は良い例ではありません。この例では、一方のパフォーマンスの向上ともう一方のパフォーマンスの向上はごくわずかであるため、読みやすさがパフォーマンスを上回ります。配列(StringBuffer)の利点は、多くの連結を行う場合にのみ明らかになります。それでも、あなたの走行距離はあなたのブラウザに非常に依存することができます。

以下は、多くの異なるブラウザーですべての異なるJavaScript連結メソッドを使用したパフォーマンスを示す詳細なパフォーマンス分析です。文字列のパフォーマンスと分析

join()1回、concat()1回、join()for、+ = for、concat()for

詳細:
Ajaxian >> IEでの文字列パフォーマンス:Array.joinと+ =の続き


9
グラフに関して、それが明らかでない場合。低いほど良いです。
Teekin

1
「まず、IE7でのパフォーマンスの向上により、大規模な文字列操作を実行するときに代替パスを使用することを検討する必要がなくなりました。反復的な状況でArray.joinを使用しても、同じ状況で+ =を使用するよりも大きな利点はありません。さらに、IE6との違いはわずかなので、特定のバージョンのフォークを気にする必要はありません。」
クリスS

2
@クリス、それは本当ではない。IE7の次の2つのフィドルを比較します:jsfiddle.net/9uS4n/5(高速)とjsfiddle.net/9uS4n/2(低速)。このjoin()手法を使用すると、パフォーマンスが少なくとも1000倍向上するようです。
カークウォル、

いい説明。:また、この確認してください iliadraznin.com/2012/03/...
will824

37

はい、それは本当ですが、気にする必要はありません。読みやすい方を選んでください。アプリのベンチマークを行う必要がある場合は、ボトルネックに焦点を当てます。

文字列の連結がボトルネックになることはないと思います。


31

マイケルハーレンに同意する。

パフォーマンスが本当に問題である場合は、配列と結合の使用も検討してください。

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));

3
正しい答えが選ばれたことは知っていますが、この答えの方が便利な例があります。
Jason Sperske、2010

1
すごい、すごい。IE7の次の2つのフィドルを比較します:jsfiddle.net/9uS4n/5(高速)とjsfiddle.net/9uS4n/2(低速)。この手法を使用すると、パフォーマンスが少なくとも1000倍向上するようです。
カークウォル、

@KirkWoll:結果を簡単に比較できるように、将来的にjsPerfを使用する可能があります。
rvighne 2014

私も最近これを行っています。.NETStringBuilderに似たコードスタイル、var sb = []; sb.push( "section 1"); sb.push( "セクション2"); return sb.join( '');
サムジョーンズ

このjsPerf jsperf.com/join-concat/2は、stackoverflow.com / questions / 16696632 / …で言及されて+=おり、それがより高速であることを示しているようです。
Ciro Santilli郝海东冠状病六四事件法轮功

18

これを試して:

var s = ["<a href='", url, "'>click here</a>"].join("");

さて、あなたの回答でリンクした投稿は、私の回答が示唆しているArray.joinの「神話」を反証しようとしています。おそらくそうではありません。実際に私が見たものの方が速いと投稿しただけです。
Rahul、2009

文字列連結のこのメソッドが大好きです。
bkwdesign 2014年

8

すでに一部のユーザーが指摘したように、これは小さな文字列には無関係です。

そして、Firefox、Safari、またはGoogle Chromeの新しいJavaScriptエンジンは、

"<a href='" + url + "'>click here</a>";

と同じくらい速いです

["<a href='", url, "'>click here</a>"].join("");

8

JavaScriptにはネイティブのStringBufferオブジェクトがないので、これは、使用しているライブラリからのものか、通常とは異なるホスト環境(つまりブラウザではない)の機能によるものだと思います。

ネイティブのStringBufferオブジェクトが生成する可能性はあるものの、ライブラリ(JSで記述)がより高速に生成することは疑わしいです。決定的な答えはプロファイラーで見つけることができます(ブラウザーで実行している場合、FirebugはFirefoxにあるJSエンジンのプロファイラーを提供します)。


6

クヌースの言葉によれば、「時期尚早の最適化はすべての悪の根源です!」いずれにせよ、わずかな差異は、結局ほとんど影響を与えないでしょう。私はもっ​​と読みやすいものを選びます。


1
前者はO(N)時間の複雑さを持っているのに対し、後者はO(N ^ 2)であるので、伝統的にStringBufferは連結よりも使用されます。いずれの場合も、使用している環境によっては、JavaScriptでO(N ^ 2)シナリオが当てはまらない場合があります。
redcalx 2011

4

読みやすい方法では、コードを見たときに人間が知覚できる時間を節約できますが、「より速い」方法では、人々がページを閲覧しているときに、気付かず、無視できるほどの時間しか無駄にしません。

私はこの投稿が不完全であることを知っていますが、これを別のスレッドだと思ってまったく違うものを誤って投稿し、投稿を削除する方法がわかりません。私の悪い…


3

jspref.comを使用すると、簡単なベンチマークを設定し、Javascriptのパフォーマンスの変化を確認するのが非常に簡単です。この質問がなされたとき、それはおそらくありませんでした。しかし、この質問に出くわした人にとっては、サイトを見る必要があります。

http://jsperf.com/string-concat-methods-testで、さまざまな連結方法の簡単なテストを行いました。


それから判断すると、+演算子との連結が間違いなく進むべき道であるように思われます。間違って読んでいない限り。それは完全にもっともらしいです。
Richard

2

私は次のような機能的なスタイルを使いたいです。

function href(url,txt) {
  return "<a href='" +url+ "'>" +txt+ "</a>"
}

function li(txt) {
  return "<li>" +txt+ "</li>"
}

function ul(arr) {
  return "<ul>" + arr.map(li).join("") + "</ul>"
}

document.write(
  ul(
    [
      href("http://url1","link1"),
      href("http://url2","link2"),
      href("http://url3","link3")
    ]
  )
)

このスタイルは読みやすく、透明に見えます。これは、コードの繰り返しを減らすユーティリティの作成につながります。

これはまた、自動的に中間文字列を使用する傾向があります。


1

私の知る限り、すべての連結はメモリの再割り当てを意味します。したがって、問題はそれを行うために使用される演算子ではなく、解決策は連結の数を減らすことです。たとえば、可能な場合は、反復構造の外で連結を行います。


これは実際に悪いアドバイスではありません、なぜそれがそんなに投票されたのか分かりません。特定の質問に答えられないことは知っていますが、一般的には良いアドバイスであると認められるに値します。
まぶたのない状態2010

0

はい、通常のベンチマークによると。EG:http : //mckoss.com/jscript/SpeedTrial.htm

しかし、小さなストリングの場合、これは無関係です。非常に大きな文字列のパフォーマンスのみを気にします。さらに、ほとんどのJSスクリプトでは、ボトルネックが十分でないため、ストリング操作でボトルネックが発生することはほとんどありません。

DOM操作を監視する方がよいでしょう。


リンクが無効になっています。https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htmは、Webアーカイブバージョンを指しています。
トニー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.