2013-09-27 16 views
5

Sto usando D3.js e spesso mi trovo dinamicamente costruendo gli attributi transform (o gli attributi). Entrambi richiedono spesso più numeri separati da virgola.Javascript concatenate array a stringa

A volte mi costruire le mie corde concatenando una serie di stringhe:

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

E a volte mi costruire le mie corde aggiungendo manualmente la virgola:

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

ho deciso che avrei dovuto provare attenersi a un metodo o all'altro, e mi chiedo quale sia l'approccio migliore da prendere.

Qui ci sono alcune cose che ho considerato:

  • So che chiamare join() è più lento di concatenare manualmente le virgole, ma è che ciò che il browser fa quando concatena una matrice in una stringa?
  • Il secondo formato funzionerà con qualsiasi browser. Ci sono dei browser che non supportano il primo formato?
  • Il primo formato utilizza meno caratteri (mantenere le dimensioni del file basse è sempre un vantaggio).
  • Personalmente, credo che il primo formato sia più leggibile.

C'è un modo decisamente migliore rispetto all'altro? O sto solo diventando pignolo?

+1

Stai solo facendo il furbo :-) Sceggerei quello più leggibile (e secondo me, quello è il secondo). – bfavaretto

risposta

9

Quando JavaScript costringe un array a una stringa, in realtà chiama: .join(',') nella matrice. Quindi otterrai prestazioni migliori con .join(',') manualmente anziché lasciarlo all'interprete per notare che stai forzando l'array. Dunque: [x, y].join(',') è la soluzione migliore (dal momento che semplifica la modifica del comportamento) e [x, y] è un po 'più lento di chiamare manualmente .join e può essere illeggibile a volte, ma è più conveniente.

+0

Buon punto su '.join (',')'. Non ho pensato a questa opzione. – Towler

+0

Sono stato sorpreso di scoprire quanto sia più veloce 'x + ',' + y'. Nel mio caso, era circa 4 volte più veloce di '[x, y]'. (http://www.jsfiddle.net/8VqEP) – Towler

4

la risposta breve: utilizzare array.join.

la risposta lunga:

Prima di tutto, la concatenazione non è più veloce rispetto all'utilizzo di Array.join(), è più lento. questo perché ogni volta che ti concateni distruggi due stringhe e ne crei una nuova.

prendere il codice seguente:

<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> 

e incollarlo in un file html. Quindi tracciarlo. Sulla mia macchina (core i7EE, 16GB RAM, dischi SSD, IE9), arr() prende 0ms e concat() richiede 12ms. Tieni presente che questo è più di un milione di iterazioni (questo stesso test sarebbe abbastanza diverso su IE6, concat() richiederebbe secondi).

In secondo luogo, la concatenazione avrà lo stesso valore di array.join quando si hanno solo due valori. Quindi, per il tuo esempio, dal punto di vista delle prestazioni, sono entrambi equivalenti. se si prende il codice sopra riportato e si cambia il valore da 1000000 a 4, sia concat che arr prendono 0ms per l'esecuzione. questo significa che la differenza per il tuo flusso particolare è inesistente o così trascurabile che non viene visualizzata in un profilo.

In terzo luogo, i browser moderni ottimizzano la concatenazione delle stringhe usando array.join() comunque, quindi la discussione è probabilmente discutibile dal punto di vista delle prestazioni.

Questo ci lascia con stile. Personalmente, non userei il primo modulo perché non mi piace concatenare manualmente le stringhe (quando hai 2 vars è piuttosto semplice, ma se avessi 10 vars? Questo farà una lunga fila di codice. E se ricevessi un array con n valori, entrasse in un ciclo for). Non userei il secondo modulo perché, come indicato in un'altra risposta, il valore è forzato a una stringa e ciò significa che sta avvenendo una trasformazione implicita. Il problema qui è la parte implicita. So che ora gli array vengono uniti con una virgola quando forzati, ma cosa succede se la specifica cambia, o qualche genio decide di cambiare l'implementazione toString di Array.prototype nella base di codice? solo per divertimento esegui questo in jsfiddle:

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

alert([1, 2]); 

Riuscite a indovinare quale sarà la risposta? (il codice sopra eseguirà lo stesso tipo di conversione per l'array come codice. coercizione tramite il metodo toString())

se si utilizza array.join (','); sarai in grado di proteggere il tuo codice in futuro affermando che 1) il tuo array sarà unito indipendentemente dall'implementazione di toString e 2) sarà unito con una virgola.

+0

Sono d'accordo con il tuo punto sulla trasformazione implicita - è qualcosa a cui non ho pensato. Non sono d'accordo, tuttavia, sul tuo test delle prestazioni. Sto costruendo la mia stringa in una singola riga di codice, non in modo iterativo in un ciclo. Un test case migliore sarebbe qualcosa di simile (vedi questo fiddle http://jsfiddle.net/8VqEP/). Vedrai qui che le valutazioni delle prestazioni nella risposta di TenorB sono accurate. – Towler

+0

il punto del test era mostrare che qualsiasi differenza è trascurabile (12 ms è quasi nulla) e per illustrare quanto sia più lenta la concatenazione di stringhe quando si lavora con stringhe grandi (1000000 iterazioni per una stringa lunga). Il tuo violino mette a confronto unendo un array vs concatenando una stringa veramente piccola. Dopo averlo modificato un po '(si stava costruendo la matrice in ogni iterazione, che può inquinare il test dal momento che stiamo definendo la concatenazione, non la creazione di oggetti), torno al secondo punto. i miei tempi erano 502, 2 e 91, cioè circa 0.000502ms per iterazione per il test più lento. trascurabile. –

+0

che ci riporta all'intento del mio post. poiché le prestazioni sono trascurabili, dovresti usare array.join per i motivi sopra indicati, –