2013-09-27 9 views
5

私はD3.jsを使用していて、自分自身がtransform属性(またはpath要素のd属性)を動的に構築していることがよくあります。これらの両方には、複数のカンマ区切り番号が必要なことがよくあります。Javascript文字列に配列を連結する

時々私は、文字列に配列を連結することで、私の文字列を構築する:

var x = 0, 
y = 1, 
path = 'M0,0 L' + [x, y]; 

そして、時には、私は手動でカンマを追加することによって、私の文字列を構築する:

var x = 0, 
y = 1, 
path = 'M0,0 L' + x + ',' + y; 

私は、私が試してみてくださいということにしましたある方法か他の方法に固執して、どちらのアプローチがより良いアプローチかと思っています。

ここで私が考えられてきたいくつかのことがあります:

  • 私はjoin()を呼び出すと、手動でカンマを連結するよりも低速であることを知っているが、それは文字列に配列を連結したときに、ブラウザが何をするかということですか?
  • 2番目の形式はどのブラウザでも動作します。最初の形式をサポートしていないブラウザはありますか?
  • 最初の形式では文字数が少なくなります(ファイルサイズを小さくすると常にプラスになります)。
  • 個人的には、最初のフォーマットが読みやすくなっていると思います。

他の方法よりも格段に良い方法がありますか?または私はちょうどニンピクされていますか?

+1

あなたはちょうどニッキーです:-)私はより読みやすいものを選んでいます(そして私の意見では、それは第2のものです)。 – bfavaretto

答えて

9

JavaScriptが配列に文字列を強制するとき、実際には配列の上に:.join(',')が呼び出されます。したがって、あなたは実際には.join(',')を使ってより良いパフォーマンスを得ることになります。それは、あなたが配列を強制することに気づくためにインタプリタに任せておくのではなくなります。したがって:x + ',' + yが最も速く、[x, y].join(',')がベストプラクティスです(動作を変更しやすくなるため)[x, y]は手動で.joinを呼び出すよりも少し遅く、時には判読できない場合がありますが、より便利です。

+0

'.join( '、')'の良い点です。私はそのオプションについて考えなかった。 – Towler

+0

私は実際にどれだけ速い 'x + '、' + y'が見つかったのか驚いた。私の場合、 '[x、y]'より約4倍速かった。 (http://www.jsfiddle.net/8VqEP) – Towler

4

短い答え:use array.join。

長い答え:

まず第一に、連結は)(array.join使用するよりも速くないが、それは遅くなります。これは、連結するたびに2つの文字列を破棄して新しい文字列を作成するためです。

<script> 
function concat(){ 
var txt = ''; 
for (var i = 0; i < 1000000; i++){ 
txt =+ i + ','; 
} 
} 

function arr(ar){ 
var txt = 'asdf' + ar; 
} 

ar = []; 
for (var i = 0; i < 1000000; i++) { 
ar.push(i); 
} 

concat(); 

arr(ar); 

alert('done!'); 
</script> 

とhtmlファイルに貼り付けます。

は、次のコードを取ります。それをプロファイルします。私のマシン(コアi7EE、16GB RAM、SSDディスク、IE9)では、arr()は0ms、concat()は12msかかります。これは百万回以上の反復であることに留意してください(この同じテストはIE6ではかなり異なるでしょう、concat()は数秒かかるでしょう)。

第2に、2つの値しか持たない場合、連結はarray.joinと同じになります。つまり、パフォーマンスの観点から見れば、どちらも同等です。上記のコードをとり、1000000を4に変更すると、concatとarrの両方が0msで実行されます。これは、特定のフローの違いが存在しないか無視できるため、プロファイルに表示されないことを意味します。

第3に、最近のブラウザでは、array.join()を使用して文字列の連結を最適化しているため、パフォーマンスの観点からは議論の対象にはなりません。

これは私たちにスタイルを残します。個人的には、手動で文字列を連結するのが好きではないので、私は最初のフォームを使用しません(2つの変数を持っているときはそれほど単純ですが、10の変数を持つとすれば本当に長いコード行になります)。そして、n個の値を持つ配列を受け取った場合は、forループになります)。私は別の答えで指摘されているように、値が文字列に強制され、暗黙的な変換が行われていることを意味するため、第2の形式を使用しません。ここでの問題は暗黙的な部分です。私は現在、配列が強制的にコンマで結合されていることを知っていますが、仕様が変更されたり、コードベースでArray.prototypeのtoString実装を変更すると決定した場合はどうなりますか?ちょうど楽しみのためにこれをjsfiddleで実行してください:

Array.prototype.toString = function() { 
return 'not the expected result!'; 
} 

alert([1, 2]); 

答えがどのようになるのでしょうか? (上記のコードは、配列と同じ種類の変換をコードと同じように実行します。toString()メソッドによる強制)

array.join( '、'); 1)配列がtoStringの実装に関係なく結合され、2)コンマで結合されることを保証することでコードを将来的に保護します。

+0

暗黙的な変換に関するあなたの意見に同意します。これは私が考えなかったものです。私はあなたのパフォーマンステストには同意しません。私は、繰り返しループではなく、1行のコードでStringを構築しています。より優れたテストケースは、このようなものになります(このフィドルhttp://jsfiddle.net/8VqEP/を参照)。ここでは、TenorBの回答の成績評価が正確であることがわかります。 – Towler

+0

テストのポイントは、どのような違いも無視できる(12msはほとんどありません)ことを示し、大きな文字列を扱う場合の文字列の連結がどれほど遅いかを示すことです(1000000回の繰り返しで長い文字列になります)。あなたのフィドルは、アレイに参加することと、実際に小さな文字列を連結することとを比較します。 (私たちがオブジェクトの作成ではなく連結をプロファイリングしているので、テストを汚染する可能性のある各反復で配列を構築していた)少し修正した後、私は第2のポイントに戻ります。私の時間は502,2,91でした。最も遅いテストでは1回の繰り返しで0.000502msでした。無視できる。 –

+0

私のポストの意図に私たちを戻します。パフォーマンスは無視できるので、上記の理由でarray.joinを使用してください。 –