è l'operatore + meno performante di StringBuffer.append ()


91

Nel mio team, di solito facciamo la concatentazione di stringhe in questo modo:

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

Ovviamente il seguente è molto più leggibile:

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

Ma gli esperti JS affermano che l' +operatore è meno performante di StringBuffer.append(). È proprio vero?


92
Non c'è StringBuffer in javascript
Tomas

7
Don, ti riferivi a Java?
James McMahon

La mia esperienza è stata che [].join('')ha mostrato un comportamento davvero cablato, quindi sono tornato a +: - /
martyglaubitz

1
So che la domanda fondamentale qui riguarda la concatenazione di stringhe, ma dovresti usare cautela quando crei elementi html come questo. Il tuo esempio potrebbe non funzionare se urlcontiene 'o \n.
styfle

Risposte:


46

Internet Explorer è l'unico browser che ne soffre davvero nel mondo di oggi. (Le versioni 5, 6 e 7 erano lente come il cane. 8 non mostra la stessa degradazione.) Inoltre, IE diventa sempre più lento quanto più lunga è la tua corda.

Se hai stringhe lunghe da concatenare, usa sicuramente una tecnica array.join. (O un wrapper StringBuffer attorno a questo, per leggibilità.) Ma se le tue stringhe sono corte non preoccuparti.


102

Il tuo esempio non è buono in quanto è molto improbabile che la performance sarà significativamente diversa. Nel tuo esempio la leggibilità dovrebbe prevalere sulle prestazioni perché il guadagno in termini di prestazioni dell'uno rispetto all'altro è trascurabile. I vantaggi di un array (StringBuffer) sono evidenti solo quando si eseguono molte concatentazioni. Anche in questo caso il tuo chilometraggio può dipendere molto dal tuo browser.

Ecco un'analisi dettagliata delle prestazioni che mostra le prestazioni utilizzando tutti i diversi metodi di concatenazione JavaScript su molti browser diversi; Prestazioni delle stringhe e analisi

join () una volta, concat () una volta, join () for, + = for, concat () for

Altro:
Ajaxian >> Prestazioni delle stringhe in IE: Array.join vs + = continua


9
Per quanto riguarda il grafico, nel caso non fosse ovvio; è meglio più basso.
Teekin

1
"Per prima cosa, con i miglioramenti delle prestazioni con IE7, non è più necessario considerare l'utilizzo di un percorso alternativo quando si eseguono operazioni su stringhe su larga scala; l'utilizzo di Array.join in una situazione iterativa non offre grandi vantaggi rispetto all'utilizzo di + = nella stessa situazione. Inoltre, le differenze con IE6 erano abbastanza lievi da consentirti di non preoccuparti di biforcare per quella specifica versione. "
Chris S,

2
@ Chris, non è vero. Confronta questi due violini in IE7 : jsfiddle.net/9uS4n/5 (veloce) vs. jsfiddle.net/9uS4n/2 (lento). Sembra che ci sia un miglioramento di almeno 1000 volte nelle prestazioni usando la join()tecnica.
Kirk Woll

Bella spiegazione. Si prega di rivedere anche questo: iliadraznin.com/2012/03/…
will824

37

Sì, è vero ma non dovrebbe importarti. Scegli quello più facile da leggere. Se devi confrontare la tua app, concentrati sui colli di bottiglia.

Immagino che la concatenazione di stringhe non sarà il tuo collo di bottiglia.


31

D'accordo con Michael Haren .

Considera anche l'uso di array e unisciti se le prestazioni sono davvero un problema.

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

3
So che è stata selezionata una risposta corretta, ma questa risposta ha un esempio più utile.
Jason Sperske

1
Wow solo Wow. Confronta questi due violini in IE7 : jsfiddle.net/9uS4n/5 (veloce) vs. jsfiddle.net/9uS4n/2 (lento). Sembra esserci un miglioramento almeno 1000 volte delle prestazioni usando questa tecnica.
Kirk Woll

@KirkWoll: Potrei voler utilizzare jsPerf in futuro in modo da poter confrontare facilmente i risultati.
rvighne

l'ho fatto anche di recente, stile di codice simile a un .NET StringBuilder, var sb = []; sb.push ("sezione 1"); sb.push ("sezione 2"); return sb.join ('');
Sam Jones


18

Prova questo:

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

Ebbene, il post a cui ti sei collegato nella tua risposta cerca specificamente di confutare il "mito" di Array.join che la mia risposta suggerisce. Quindi forse no. Ho semplicemente pubblicato quello che ho visto essere più veloce nella pratica.
Rahul

amo questo metodo di concatenazione di stringhe.
bkwdesign

8

Come già notato da alcuni utenti: questo è irrilevante per stringhe piccole.

E i nuovi motori JavaScript in Firefox, Safari o Google Chrome ottimizzano così

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

è veloce quanto

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

8

JavaScript non ha un oggetto StringBuffer nativo, quindi presumo che provenga da una libreria che stai utilizzando o da una funzionalità di un ambiente host insolito (cioè non un browser).

Dubito che una libreria (scritta in JS) produrrebbe qualcosa di più veloce, anche se potrebbe farlo un oggetto StringBuffer nativo. La risposta definitiva può essere trovata con un profiler (se stai utilizzando un browser, Firebug ti fornirà un profiler per il motore JS trovato in Firefox).


6

Nelle parole di Knuth, "l'ottimizzazione prematura è la radice di tutti i mali!" La piccola differenza in entrambi i casi molto probabilmente non avrà molto effetto alla fine; Sceglierei quello più leggibile.


1
Tradizionalmente StringBuffer viene utilizzato sulla concatenazione perché il primo ha una complessità temporale O (N) mentre il secondo come O (N ^ 2), quindi la differenza è significativa per N grande (ma non per N piccolo). In ogni caso lo scenario O (N ^ 2) potrebbe non essere il caso di JavaScript a seconda dell'ambiente in uso.
redcalx

4

Il metodo più facile da leggere fa risparmiare agli esseri umani quantità di tempo percettibili quando guardano il codice, mentre il metodo "più veloce" spreca solo quantità di tempo impercettibili e probabilmente trascurabili quando le persone stanno navigando nella pagina.

So che questo post è scadente, ma ho accidentalmente pubblicato qualcosa di completamente diverso pensando che fosse un thread diverso e non so come eliminare i post. Colpa mia...


3

È abbastanza facile impostare un benchmark veloce e controllare le variazioni delle prestazioni di Javascript utilizzando jspref.com . Che probabilmente non c'era quando è stata posta questa domanda. Ma per le persone che si imbattono in questa domanda dovrebbero dare un'occhiata al sito.

Ho fatto un rapido test di vari metodi di concatenazione su http://jsperf.com/string-concat-methods-test .


A giudicare da ciò, al giorno d'oggi sembra che la concatenazione con l'operatore + sia decisamente la strada da percorrere. A meno che non lo stia leggendo male. Il che è del tutto plausibile.
Richard

2

Mi piace usare uno stile funzionale, come ad esempio:

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")
    ]
  )
)

Questo stile sembra leggibile e trasparente. Porta alla creazione di utilità che riducono la ripetizione nel codice.

Questo tende anche a utilizzare automaticamente stringhe intermedie.


1

Per quanto ne so, ogni concatenazione implica una riallocazione della memoria. Quindi il problema non è l'operatore utilizzato per farlo, la soluzione è ridurre il numero di concatenazioni. Ad esempio, fai le concatenazioni al di fuori delle strutture di iterazione quando puoi.


Questo in realtà non è un cattivo consiglio, non so perché sia ​​stato votato così tanto. So che non risponde alla domanda specifica, ma merita il riconoscimento in quanto generalmente un buon consiglio.
mancanza di palpebre

0

Sì, secondo i soliti benchmark. EG: http://mckoss.com/jscript/SpeedTrial.htm .

Ma per le corde piccole, questo è irrilevante. Ti interesseranno solo le esibizioni su corde molto grandi. Inoltre, nella maggior parte degli script JS, il collo di bottiglia è raramente sulle manipolazioni delle stringhe poiché non ce n'è abbastanza.

Faresti meglio a guardare la manipolazione del DOM.


Il collegamento è morto .. https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm punta alla versione dell'archivio web.
Tony
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.