2008-09-21 17 views
87

En mi equipo, que normalmente no concatenación cadena como esta:es el operador + menos eficiente que StringBuffer.append()

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

Obviamente, el 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?

+85

No hay StringBuffer en javascript – Tomas

+6

Don, ¿te refieres a Java? –

+0

Mi experiencia fue que '[] .join ('')' ha mostrado un comportamiento realmente conectado, así que volví a +: -/ – martyglaubitz

Respuesta

45

Internet Explorer es el único navegador que en realidad sufre de esto en el mundo de hoy. (Las versiones 5, 6 y 7 fueron dog slow. 8 no muestran la misma degradación). Además, IE se vuelve cada vez más lenta cuanto más larga es la cadena.

Si tiene cadenas largas para concatenar, entonces definitivamente use una técnica de arreglo. (O algo de envoltura StringBuffer alrededor de esto, para facilitar la lectura). Pero si tus cadenas son cortas, no te molestes.

36

Sí, es cierto, pero no debería importarle. Ve con el que es 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.

18

Prueba esto:

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

Bueno, la publicación a la que se vinculó en su respuesta específicamente intenta refutar el "mito" de Array.join que sugiere mi respuesta. Entonces tal vez no. Simplemente publiqué lo que he visto para ser más rápido en la práctica. – Rahul

+0

encanta este método de cadena concat. – bkwdesign

8

JavaScript no tiene un objeto StringBuffer nativa, así que estoy asumiendo que esto es de una biblioteca que está utilizando, o una característica de un entorno de acogida inusual (es decir, no una navegador).

Dudo que una biblioteca (escrita en JS) produzca algo más rápido, aunque un objeto nativo StringBuffer podría. 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).

6

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

+1

Tradicionalmente StringBuffer se usa sobre la concatenación porque el primero tiene una complejidad de tiempo O (N) mientras que el último como 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

0

Sí, de acuerdo con los puntos de referencia habituales. E.G: http://mckoss.com/jscript/SpeedTrial.htm.

Pero para las cuerdas pequeñas, esto es irrelevante. Solo le importará el rendimiento en cadenas muy grandes. Además, en la mayoría de las secuencias de comandos de JS, el cuello de la botella rara vez se manipula con cuerdas, ya que no hay suficiente.

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

102

Su ejemplo no es bueno porque es muy poco probable que el rendimiento sea significativamente diferente. En su ejemplo, la legibilidad debe prevalecer sobre el rendimiento porque la ganancia de rendimiento de uno frente al otro es insignificante. Los beneficios de una matriz (StringBuffer) solo son aparentes cuando se hacen muchas concatentaciones. Incluso entonces su kilometraje puede muy dependiendo de su navegador.

Aquí hay un análisis de rendimiento detallado que muestra el rendimiento utilizando todos los diferentes métodos de concatenación de JavaScript en muchos navegadores diferentes; String Performance an Analysis

join() once, concat() once, join() for, += for, concat() for

Más:
Ajaxian >> String Performance in IE: Array.join vs += continued

+9

En cuanto al gráfico, en caso de que no sea obvio; más bajo es mejor. – Teekin

+1

"Lo primero es lo primero con las mejoras de rendimiento con IE7, ya no es necesario considerar utilizar una ruta alternativa cuando se realizan operaciones de cadena a gran escala; el uso de Array.join en una situación iterativa no ofrece mayores ventajas que usar + = en la misma situación Además, las diferencias con IE6 fueron lo suficientemente leves como para permitirte no molestarte en horquillas para esa versión específica ". –

+2

@Chris, eso no es verdad. Compare estos dos violines en ** IE7 **: http://jsfiddle.net/9uS4n/5/ (rápido) vs. http://jsfiddle.net/9uS4n/2/ (lento). Parece haber al menos una mejora de 1000 veces en el rendimiento utilizando la técnica 'join()'. –

29

mostró de acuerdo con Michael Haren.

Considere también el uso de matrices y únete si el rendimiento es realmente un problema.

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

Sé que se ha seleccionado una respuesta correcta, pero esta respuesta tiene un ejemplo más útil. –

+0

Guau, solo guau. Compare estos dos violines en ** IE7 **: http://jsfiddle.net/9uS4n/5/ (rápido) vs. http://jsfiddle.net/9uS4n/2/ (lento). Parece que hay al menos una mejora de 1000 veces en el rendimiento con esta técnica. –

+0

buena técnica ... – rxlky

1

Por lo que sabemos, cada concatenación implica una reasignación de memoria. Entonces, el problema no es que el operador solía hacerlo, la solución es reducir el número de concatenaciones. Por ejemplo, haz las concatenaciones fuera de las estructuras de iteración cuando puedas.

+0

Esto no es realmente un mal consejo, no sé por qué se votó tanto. Sé que no responde a la pregunta específica, pero merece reconocimiento como un buen consejo en general. – eyelidlessness

7

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

Y nuevos motores de JavaScript en Firefox, Safari o Google Chrome optimizar de manera

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

es tan rápido como

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

me gusta usar estilo funcional, tales 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 se ve legible y transparente. Conduce a la creación de utilidades que reduce la repetición en el código.

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

3

Es muy fácil establecer un punto de referencia rápido y comprobar las variaciones de rendimiento de Javascript usando jspref.com. Lo cual probablemente no existía cuando se hizo esta pregunta. Pero para las personas que tropiezan con esta pregunta, deben tomar alook en el sitio.

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

+0

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

4

El método más fácil de leer ahorra a los humanos cantidades perceptibles de tiempo 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 coja, pero accidentalmente publiqué algo completamente diferente pensando que esto era un hilo diferente y no sé cómo eliminar publicaciones. Mi mal ...

Cuestiones relacionadas