est l'opérateur + moins performant que StringBuffer.append ()

91

Dans mon équipe, nous faisons généralement la concatentation de chaînes comme ceci:

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

Évidemment, ce qui suit est beaucoup plus lisible:

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

Mais les experts JS affirment que l' +opérateur est moins performant que StringBuffer.append(). Est-ce vraiment vrai?

Dónal
la source
92
Il n'y a pas de StringBuffer en javascript
Tomas
7
Don, faisiez-vous référence à Java?
James McMahon
Mon expérience [].join('')a montré un comportement vraiment câblé, alors je reviens à +: - /
martyglaubitz
1
Je sais que la question fondamentale ici concerne la concaténation de chaînes, mais vous devez faire preuve de prudence lors de la création d'éléments html comme celui-ci. Votre exemple pourrait casser si le urlcontient 'ou \n.
styfle
Possibilité de dupliquer le moyen le plus efficace de concaténer des chaînes en JavaScript?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

46

Internet Explorer est le seul navigateur qui en souffre vraiment dans le monde d'aujourd'hui. (Les versions 5, 6 et 7 étaient trop lentes. 8 ne montre pas la même dégradation.) De plus, IE devient de plus en plus lent, plus votre corde est longue.

Si vous avez de longues chaînes à concaténer, utilisez définitivement une technique array.join. (Ou un wrapper StringBuffer autour de cela, pour plus de lisibilité.) Mais si vos chaînes sont courtes, ne vous inquiétez pas.

pcorcoran
la source
102

Votre exemple n'est pas bon dans la mesure où il est très peu probable que la performance soit sensiblement différente. Dans votre exemple, la lisibilité devrait l'emporter sur les performances car le gain de performance de l'un par rapport à l'autre est négligeable. Les avantages d'un tableau (StringBuffer) ne sont apparents que lorsque vous effectuez de nombreuses concatentations. Même dans ce cas, votre kilométrage peut dépendre de votre navigateur.

Voici une analyse détaillée des performances qui montre les performances en utilisant toutes les différentes méthodes de concaténation JavaScript sur de nombreux navigateurs différents; Performance des chaînes et analyse

join () une fois, concat () une fois, join () pour, + = pour, concat () pour

Plus:
Ajaxian >> Performances des chaînes dans IE: Array.join vs + = suite

Eric Schoonover
la source
9
Concernant le graphique, au cas où ce ne serait pas évident; plus bas c'est mieux.
Teekin
1
«Tout d'abord, avec les améliorations de performances avec IE7, nous n'avons plus besoin d'envisager d'utiliser un autre chemin lors d'opérations sur des chaînes à grande échelle; utiliser Array.join dans une situation itérative ne vous donne pas d'avantages majeurs que d'utiliser + = dans la même situation. De plus, les différences avec IE6 étaient suffisamment légères pour vous permettre de ne pas déranger pour cette version spécifique. "
Chris S
2
@Chris, ce n'est pas vrai. Comparez ces deux violons dans IE7 : jsfiddle.net/9uS4n/5 (rapide) vs jsfiddle.net/9uS4n/2 (lent). Il semble y avoir une amélioration d'au moins 1000 fois la performance en utilisant la join()technique.
Kirk Woll
Belle explication. Veuillez également consulter ceci: iliadraznin.com/2012/03/…
will824
37

Oui c'est vrai mais vous ne devriez pas vous en soucier. Choisissez celui qui est plus facile à lire. Si vous devez évaluer votre application, concentrez-vous sur les goulots d'étranglement.

Je suppose que la concaténation de chaînes ne sera pas votre goulot d'étranglement.

Michael Haren
la source
31

D'accord avec Michael Haren .

Pensez également à l'utilisation de tableaux et à la jointure si les performances sont effectivement un problème.

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));
Frank Krueger
la source
3
Je sais qu'une réponse correcte a été choisie, mais cette réponse a un exemple plus utile.
Jason Sperske
1
Wow, juste wow. Comparez ces deux violons dans IE7 : jsfiddle.net/9uS4n/5 (rapide) vs jsfiddle.net/9uS4n/2 (lent). Il semble y avoir au moins 1000 fois une amélioration des performances en utilisant cette technique.
Kirk Woll
@KirkWoll: Pourrait vouloir utiliser jsPerf à l'avenir afin que nous puissions facilement comparer les résultats.
rvighne
je l'ai fait récemment aussi, un style de code similaire à un StringBuilder .NET, var sb = []; sb.push ("section 1"); sb.push ("section 2"); return sb.join ('');
Sam Jones
Ce jsPerf jsperf.com/join-concat/2 mentionné à: stackoverflow.com/questions/16696632/... semble indiquer que +=c'est plus rapide.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
18

Essaye ça:

var s = ["<a href='", url, "'>click here</a>"].join("");
Rahul
la source
Eh bien, le post auquel vous avez lié dans votre réponse essaie spécifiquement de réfuter le "mythe" de Array.join que ma réponse suggère. Alors peut-être pas. J'ai simplement posté ce que j'ai vu plus rapide dans la pratique.
Rahul le
J'adore cette méthode de concat de chaîne.
bkwdesign
8

Comme déjà certains utilisateurs l'ont noté: ceci n'est pas pertinent pour les petites chaînes.

Et les nouveaux moteurs JavaScript de Firefox, Safari ou Google Chrome optimisent

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

est aussi rapide que

["<a href='", url, "'>click here</a>"].join("");
un mélange
la source
8

JavaScript n'a pas d'objet StringBuffer natif, donc je suppose que cela provient d'une bibliothèque que vous utilisez, ou d'une fonctionnalité d'un environnement hôte inhabituel (c'est-à-dire pas un navigateur).

Je doute qu'une bibliothèque (écrite en JS) produise quelque chose plus rapidement, bien qu'un objet StringBuffer natif puisse le faire. La réponse définitive peut être trouvée avec un profileur (si vous utilisez un navigateur, Firebug vous fournira un profileur pour le moteur JS de Firefox).

Quentin
la source
6

Selon les termes de Knuth, "l'optimisation prématurée est la racine de tout mal!" La petite différence de toute façon n'aura probablement pas beaucoup d'effet à la fin; Je choisirais le plus lisible.

William Keller
la source
1
Traditionnellement, StringBuffer est utilisé sur la concaténation parce que le premier a une complexité temporelle O (N) tandis que le second est O (N ^ 2), donc la différence est significative pour un grand N (mais pas pour un petit N). Dans tous les cas, le scénario O (N ^ 2) peut ne pas être le cas en JavaScript en fonction de l'environnement utilisé.
redcalx
4

La méthode la plus facile à lire fait gagner un temps perceptible aux humains lorsqu'ils regardent le code, tandis que la méthode «plus rapide» ne gaspille qu'un temps imperceptible et probablement négligeable lorsque les gens parcourent la page.

Je sais que ce message est nul, mais j'ai accidentellement publié quelque chose de complètement différent en pensant que c'était un fil différent et je ne sais pas comment supprimer des messages. Ma faute...

Ed Kern
la source
3

Il est assez facile de configurer un benchmark rapide et de vérifier les variations de performances Javascript à l'aide de jspref.com . Ce qui n'était probablement pas là lorsque cette question a été posée. Mais pour les gens qui trébuchent sur cette question, ils devraient consulter le site.

J'ai fait un test rapide de diverses méthodes de concaténation sur http://jsperf.com/string-concat-methods-test .

James McMahon
la source
À en juger par cela, il semble que de nos jours, la concaténation avec l'opérateur + est définitivement la voie à suivre. Sauf si je lis mal. Ce qui est tout à fait plausible.
Richard
2

J'aime utiliser un style fonctionnel, tel que:

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

Ce style semble lisible et transparent. Cela conduit à la création d'utilitaires qui réduisent la répétition dans le code.

Cela a également tendance à utiliser automatiquement des chaînes intermédiaires.

jasonc65
la source
1

Autant que je sache, chaque concaténation implique une réallocation de mémoire. Le problème n'est donc pas l'opérateur utilisé pour le faire, la solution est de réduire le nombre de concaténations. Par exemple, faites les concaténations en dehors des structures d'itération lorsque vous le pouvez.

David Ameller
la source
Ce n'est pas vraiment un mauvais conseil, je ne sais pas pourquoi il a tant voté. Je sais qu'il ne répond pas à la question précise, mais il mérite d'être reconnu comme étant généralement un bon conseil.
paupière
0

Oui, selon les benchmarks habituels. EG: http://mckoss.com/jscript/SpeedTrial.htm .

Mais pour les petites chaînes, cela n'a pas d'importance. Vous ne vous soucierez que des performances sur de très grosses cordes. De plus, dans la plupart des scripts JS, le goulot d'étranglement est rarement sur les manipulations de chaîne car il n'y en a pas assez.

Vous feriez mieux de regarder la manipulation du DOM.

e-satis
la source
Le lien est mort. Https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm pointe vers la version de l'archive Web.
Tony