¿JavaScript utiliza cadenas inmutables o mutables? ¿Necesito un "generador de cadenas"?
javascript
string
En desarrolloChris
fuente
fuente
Respuestas:
Son inmutables. No puede cambiar un carácter dentro de una cadena con algo como
var myString = "abbdef"; myString[2] = 'c'
. Los métodos de manipulación de cadenas, comotrim
,slice
devuelven nuevas cadenas.Del mismo modo, si tiene dos referencias a la misma cadena, modificar una no afecta a la otra.
Sin embargo, siempre escuché lo que Ash mencionó en su respuesta (que usar Array.join es más rápido para la concatenación), así que quería probar los diferentes métodos para concatenar cadenas y abstraer la forma más rápida en un StringBuilder. Escribí algunas pruebas para ver si esto es cierto (¡no lo es!).
Esto era lo que creía que sería la forma más rápida, aunque seguía pensando que agregar una llamada al método podría hacerlo más lento ...
Aquí hay pruebas de velocidad de rendimiento. Los tres crean una cadena gigantesca compuesta de concatenación
"Hello diggity dog"
cien mil veces en una cadena vacía.He creado tres tipos de pruebas
Array.push
yArray.join
Array.push
, luego usarArray.join
Entonces creé los mismos tres pruebas mediante la abstracción de ellas en
StringBuilderConcat
,StringBuilderArrayPush
yStringBuilderArrayIndex
http://jsperf.com/string-concat-without-sringbuilder/5 Por favor, ir allí y ejecutar pruebas para que podamos obtener una muestra agradable. Tenga en cuenta que solucioné un pequeño error, por lo que los datos de las pruebas se borraron, actualizaré la tabla una vez que haya suficientes datos de rendimiento. Vaya a http://jsperf.com/string-concat-without-sringbuilder/5 para ver la tabla de datos anterior.Aquí hay algunos números (última actualización en Ma5rch 2018), si no desea seguir el enlace. El número en cada prueba está en 1000 operaciones / segundo ( más alto es mejor )
Recomendaciones
Hoy en día, todos los navegadores de hoja perenne manejan bien la concatenación de cadenas.
Array.join
solo ayuda a IE 11En general, Opera es más rápido, 4 veces más rápido que Array.
Firefox es el segundo y
Array.join
es solo un poco más lento en FF pero considerablemente más lento (3x) en Chrome.Chrome es tercero, pero el concat de cadena es 3 veces más rápido que Array.join
Crear un StringBuilder parece no afectar demasiado el rendimiento.
Espero que alguien más encuentre esto útil
Caso de prueba diferente
Como @RoyTinker pensó que mi prueba era defectuosa, creé un nuevo caso que no crea una cadena grande al concatenar la misma cadena, utiliza un carácter diferente para cada iteración. La concatenación de cuerdas todavía parecía más rápida o igual de rápida. Hagamos que esas pruebas se ejecuten.
Sugiero que todos sigan pensando en otras formas de probar esto, y siéntanse libres de agregar nuevos enlaces a los diferentes casos de prueba a continuación.
http://jsperf.com/string-concat-without-sringbuilder/7
fuente
join
concatenación de cadenas versus, por lo tanto, construir la matriz antes de la prueba. No creo que sea trampa si se entiende ese objetivo (yjoin
enumera la matriz internamente, por lo que tampoco es trampa omitir unfor
bucle de lajoin
prueba).Array.join
del libro de rinocerontes :
fuente
null
undefined
number
yboolean
. Las cadenas se asignan por valor y no por referencia y se pasan como tales. Por lo tanto, las cadenas no son solo inmutables, son un valor . Cambiar la cadena"hello"
a ser"world"
es como decidir que de ahora en adelante el número 3 es el número 4 ... no tiene sentido.var a = "hello";var b=a;a.x=5;console.log(a.x,b.x);
String
objetos creados con el constructor de cadenas son envoltorios alrededor de los valores de cadena de JavaScript. Puede acceder al valor de cadena del tipo en caja utilizando la.valueOf()
función; esto también es cierto para losNumber
objetos y los valores numéricos. Es importante tener en cuenta que losString
objetos creados usandonew String
no son cadenas reales, sino envoltorios o cajas alrededor de las cadenas. Ver es5.github.io/#x15.5.2.1 . Sobre cómo las cosas se convierten en objetos, consulte es5.github.io/#x9.9Consejo de rendimiento:
Si tiene que concatenar cadenas grandes, coloque las partes de la cadena en una matriz y use el
Array.Join()
método para obtener la cadena general. Esto puede ser muchas veces más rápido para concatenar una gran cantidad de cadenas.No hay
StringBuilder
en JavaScript.fuente
Solo para aclarar para mentes simples como la mía (de MDN ):
Inmutable significa que:
Parece que estamos mutando la cadena 'immutableString', pero no lo estamos. En lugar:
fuente
El valor del tipo de cadena es inmutable, pero el objeto String, que se crea utilizando el constructor String (), es mutable, porque es un objeto y puede agregarle nuevas propiedades.
Mientras tanto, aunque puede agregar nuevas propiedades, no puede cambiar las propiedades ya existentes
Una captura de pantalla de una prueba en la consola de Chrome
En conclusión, 1. todo el valor del tipo de cadena (tipo primitivo) es inmutable. 2. El objeto String es mutable, pero el valor del tipo de cadena (tipo primitivo) que contiene es inmutable.
fuente
new String
genera un envoltorio mutable alrededor de una cadena inmutableString
objeto (contenedor), lo que significa que no es inmutable (de forma predeterminada; como cualquier otro objeto que pueda invocarObject.freeze
para que sea inmutable). Pero un tipo de valor de cadena primitivo, ya sea contenido en unString
contenedor de objetos o no, siempre es inmutable.Las cadenas son inmutables : no pueden cambiar, solo podemos hacer nuevas cadenas.
Ejemplo:
fuente
Con respecto a su pregunta (en su comentario a la respuesta de Ash) sobre el StringBuilder en ASP.NET Ajax, los expertos parecen estar en desacuerdo sobre este.
Christian Wenz dice en su libro Programming ASP.NET AJAX (O'Reilly) que "este enfoque no tiene ningún efecto medible en la memoria (de hecho, la implementación parece ser un poco más lenta que el enfoque estándar)".
Por otro lado, Gallo et al dicen en su libro ASP.NET AJAX in Action (Manning) que "cuando el número de cadenas para concatenar es mayor, el generador de cadenas se convierte en un objeto esencial para evitar grandes caídas de rendimiento".
Supongo que tendrías que hacer tu propia evaluación comparativa y los resultados también pueden diferir entre los navegadores. Sin embargo, incluso si no mejora el rendimiento, podría considerarse "útil" para los programadores que están acostumbrados a codificar con StringBuilders en lenguajes como C # o Java.
fuente
Es una publicación tardía, pero no encontré una buena cita entre las respuestas.
Aquí hay un definitivo, excepto de un libro confiable:
Ahora, la respuesta que cita el extracto del libro de Rhino es correcta sobre la inmutabilidad de las cadenas, pero es incorrecta al decir "Las cadenas se asignan por referencia, no por valor". (Probablemente, originalmente tenían la intención de poner las palabras de manera opuesta).
El concepto erróneo de "referencia / valor" se aclara en el capítulo "JavaScript profesional", denominado "Valores primitivos y de referencia":
eso se opone a los objetos :
fuente
Las cadenas de JavaScript son de hecho inmutables.
fuente
Las cadenas en Javascript son inmutables
fuente