es el operador + menos eficaz que StringBuffer.append ()

91

En mi equipo, normalmente hacemos una concatenación de cadenas como esta:

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

Obviamente, lo siguiente es mucho más legible:

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

Pero los expertos de JS afirman que el +operador es menos eficiente que StringBuffer.append(). ¿Es esto realmente cierto?

Dónal
fuente
92
No hay StringBuffer en javascript
Tomas
7
Don, ¿te refieres a Java?
James McMahon
Mi experiencia fue que [].join('')ha mostrado un comportamiento realmente cableado, así que volví a +: - /
martyglaubitz
1
Sé que la pregunta fundamental aquí es sobre la concatenación de cadenas, pero debe tener cuidado al crear elementos html como este. Su ejemplo podría romperse si urlcontiene 'o \n.
styfle
¿Posible duplicado de la forma más eficiente de concatenar cadenas en JavaScript?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

46

Internet Explorer es el único navegador que realmente sufre de esto en el mundo actual. (Las versiones 5, 6 y 7 eran muy lentas. La 8 no muestra la misma degradación). Además, IE se vuelve más y más lento cuanto más larga es la cuerda.

Si tiene cadenas largas para concatenar, definitivamente use una técnica array.join. (O algún envoltorio StringBuffer alrededor de esto, para facilitar la lectura). Pero si sus cadenas son cortas, no se moleste.

pcorcoran
fuente
102

Su ejemplo no es bueno ya que es muy poco probable que el rendimiento sea significativamente diferente. En su ejemplo, la legibilidad debería triunfar sobre el rendimiento porque la ganancia de rendimiento de uno frente al otro es insignificante. Los beneficios de una matriz (StringBuffer) solo son evidentes cuando se realizan muchas concatenciones. Incluso entonces, su kilometraje puede depender mucho de su navegador.

A continuación, se muestra un análisis de rendimiento detallado que muestra el rendimiento utilizando los diferentes métodos de concatenación de JavaScript en muchos navegadores diferentes; Análisis de rendimiento de cadenas

join () una vez, concat () una vez, join () para, + = para, concat () para

Más:
Ajaxian >> Rendimiento de cadenas en IE: Array.join vs + = continúa

Eric Schoonover
fuente
9
Respecto al gráfico, por si no es obvio; más bajo es mejor.
Teekin
1
"Lo primero es lo primero con las mejoras de rendimiento con IE7, ya no necesitamos considerar el uso de una ruta alternativa al realizar operaciones de cadenas a gran escala; usar Array.join en una situación iterativa no le brinda mayores ventajas que usar + = en la misma situación. Además, las diferencias con IE6 eran lo suficientemente leves como para permitirle no molestarse en bifurcar esa versión específica ".
Chris S
2
@Chris, eso no es cierto. Compare estos dos violines en IE7 : jsfiddle.net/9uS4n/5 (rápido) vs.jsfiddle.net/9uS4n/2 (lento). Parece haber al menos una mejora de 1000 veces en el rendimiento utilizando la join()técnica.
Kirk Woll
Buena explicación. Por favor, revise también esto: iliadraznin.com/2012/03/…
will824
37

Sí, es cierto, pero no debería importarte. Elija el que sea más fácil de leer. Si tiene que comparar su aplicación, concéntrese en los cuellos de botella.

Supongo que la concatenación de cadenas no será su cuello de botella.

Michael Haren
fuente
31

De acuerdo con Michael Haren .

También considere el uso de matrices y únase si el rendimiento es realmente un problema.

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));
Frank Krueger
fuente
3
Sé que se ha seleccionado una respuesta correcta, pero esta respuesta tiene un ejemplo más útil.
Jason Sperske
1
Wow solo wow. Compare estos dos violines en IE7 : jsfiddle.net/9uS4n/5 (rápido) vs.jsfiddle.net/9uS4n/2 (lento). Parece haber al menos una mejora de 1000 veces en el rendimiento utilizando esta técnica.
Kirk Woll
@KirkWoll: Es posible que desee utilizar jsPerf en el futuro para que podamos comparar fácilmente los resultados.
rvighne
También he estado haciendo esto últimamente, un estilo de código similar a un .NET StringBuilder, var sb = []; sb.push ("sección 1"); sb.push ("sección 2"); return sb.join ('');
Sam Jones
Este jsPerf jsperf.com/join-concat/2 mencionado en: stackoverflow.com/questions/16696632/… parece indicar que +=es más rápido.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
18

Prueba esto:

var s = ["<a href='", url, "'>click here</a>"].join("");
Rahul
fuente
Bueno, la publicación a la que se vinculó en su respuesta trata específicamente de refutar el "mito" de Array. Únase a lo que sugiere mi respuesta. Así que quizás no. Simplemente publiqué lo que he visto que es más rápido en la práctica.
Rahul
Me encanta este método de cadena concat.
bkwdesign
8

Como ya han señalado algunos usuarios: esto es irrelevante para cadenas pequeñas.

Y los nuevos motores de JavaScript en Firefox, Safari o Google Chrome optimizan

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

es tan rápido como

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

JavaScript no tiene un objeto StringBuffer nativo, así que supongo que esto es de una biblioteca que está usando, o una característica de un entorno de host inusual (es decir, no un navegador).

Dudo que una biblioteca (escrita en JS) produzca algo más rápido, aunque un objeto StringBuffer nativo podría hacerlo. La respuesta definitiva se puede encontrar con un generador de perfiles (si está ejecutando en un navegador, Firebug le proporcionará un generador de perfiles para el motor JS que se encuentra en Firefox).

Quentin
fuente
6

En palabras de Knuth, "¡la optimización prematura es la raíz de todos los males!" La pequeña diferencia en ambos sentidos probablemente no tendrá mucho efecto al final; Elegiría el más legible.

William Keller
fuente
1
Tradicionalmente, StringBuffer se usa sobre la concatenación porque el primero tiene una complejidad de tiempo O (N) mientras que el segundo es O (N ^ 2), por lo que la diferencia es significativa para N grande (pero no para N pequeño). En cualquier caso, el escenario O (N ^ 2) puede no ser el caso en JavaScript dependiendo del entorno en uso.
redcalx
4

El método más fácil de leer ahorra a los humanos una cantidad de tiempo perceptible al mirar el código, mientras que el método "más rápido" solo desperdicia cantidades de tiempo imperceptibles y probablemente insignificantes cuando las personas navegan por la página.

Sé que esta publicación es poco convincente, pero accidentalmente publiqué algo completamente diferente pensando que era un hilo diferente y no sé cómo eliminar publicaciones. Culpa mía...

Ed Kern
fuente
3

Es bastante fácil configurar un punto de referencia rápido y ver las variaciones de rendimiento de Javascript usando jspref.com . Lo que probablemente no existía cuando se hizo esta pregunta. Pero para las personas que se encuentran con esta pregunta, deberían echar un vistazo al sitio.

Hice una prueba rápida de varios métodos de concatenación en http://jsperf.com/string-concat-methods-test .

James McMahon
fuente
A juzgar por eso, parece que hoy en día la concatenación con el operador + es definitivamente el camino a seguir. A menos que lo esté leyendo mal. Lo cual es completamente plausible.
Richard
2

Me gusta usar un estilo funcional, como:

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

Este estilo parece legible y transparente. Conduce a la creación de utilidades que reducen la repetición en el código.

Esto también tiende a utilizar cadenas intermedias automáticamente.

jasonc65
fuente
1

Hasta donde yo sé, cada concatenación implica una reasignación de memoria. Entonces, el problema no es el operador que está acostumbrado a hacerlo, la solución es reducir el número de concatenaciones. Por ejemplo, haga las concatenaciones fuera de las estructuras de iteración cuando pueda.

David Ameller
fuente
En realidad, este no es un mal consejo, no sé por qué se ha rechazado tanto. Sé que no responde a la pregunta específica, pero merece un reconocimiento como un buen consejo en general.
párpados
0

Sí, según los benchmarks habituales. Por ejemplo: http://mckoss.com/jscript/SpeedTrial.htm .

Pero para las cuerdas pequeñas, esto es irrelevante. Solo te interesarán las interpretaciones con cuerdas muy grandes. Además, en la mayoría de los scripts de JS, el cuello de botella rara vez se encuentra en las manipulaciones de la cadena, ya que no hay suficiente.

Será mejor que observe la manipulación del DOM.

e-satis
fuente
El enlace está muerto ... https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm apunta a la versión del archivo web.
Tony