¿Por qué es tan malo para la concatenación?

44

Todo el mundo sigue diciendo que uno de los problemas de JavaScript es usar + [ example ] para concatenación de cadenas. Algunos dicen que el problema no es usar + , es una coacción de tipo [ver los comentarios del ejemplo anterior]. Pero los lenguajes fuertemente tipados usan + para los tipos de concatenación y coacción sin ningún problema. Por ejemplo, en C #:

int number = 1;
MyObject obj = new MyObject();

var result = "Hello" + number + obj;
// is equivalent to
string result = "hello" + number.ToString() + obj.ToString();

Entonces, ¿por qué la concatenación de cadenas en JavaScript es un problema tan grande?

    
pregunta configurator 06.07.2011 - 21:20

4 respuestas

68

Considere este pedazo de código JavaScript:

var a = 10;
var b = 20;
console.log('result is ' + a + b);

Esto se registrará

  

el resultado es 1020

Lo más probable es que no sea lo que se pretendía, y puede ser un error difícil de rastrear.

    
respondido por el Mchl 06.07.2011 - 21:59
41

Cuando dices "malo", ¿quieres decir "incorrecto" o "lento"? El argumento sobre el uso de operadores matemáticos para hacer la concatenación de cadenas es posiblemente un argumento "incorrecto", pero también se puede argumentar que usar + para hacer mucho de concatenación de cadenas puede ser muy lento.

No hablamos de "Hello" + number cuando hablamos de rendimiento, hablamos de crear una cadena relativamente grande añadiéndolo repetidamente en un bucle.

var combined = "";
for (var i = 0; i < 1000000; i++) {
    combined = combined + "hello ";
}

En JavaScript (y C # para el caso) las cadenas son inmutables. Nunca se pueden cambiar, solo se pueden reemplazar con otras cadenas. Probablemente sepa que combined + "hello " no modifica directamente la variable combined : la operación crea una nueva cadena que es el resultado de concatenar las dos cadenas juntas, pero luego debe asignar esa nueva cadena a la combined . variable si quieres que se cambie.

Entonces, lo que este bucle está haciendo es crear un millón de objetos de cadena diferentes y desechar 999.999 de ellos. Crear tantas cadenas que crecen continuamente en tamaño no es rápido, y ahora el recolector de basura tiene mucho trabajo que hacer para limpiar después de esto.

C # tiene exactamente el mismo problema, que se resuelve en ese entorno mediante el StringBuilder clase. En JavaScript, obtendrás un rendimiento mucho mejor al construir una matriz de todas las cadenas que deseas concatenar, y luego unirlas una vez al final, en lugar de un millón de veces en el bucle:

var parts = [];
for (var i = 0; i < 1000000; i++) {
    parts.push("hello");
}
var combined = parts.join(" ");
    
respondido por el Joel Mueller 06.07.2011 - 22:14
14

No es malo usar + tanto para la suma como para la concatenación, siempre que solo puedas sumar números y solo concatenar cadenas. Sin embargo, Javascript se convertirá automáticamente entre números y cadenas según sea necesario, por lo que tiene:

3 * 5 => 15
"3" * "5" => 15
2 + " fish" => "2 fish"
"3" + "5" => "35"  // hmmm...

Quizás más simple, la sobrecarga de "+" en presencia de conversión automática de tipos rompe la asociatividad esperada del operador +:

("x" + 1) + 3 != "x" + (1 + 3)
    
respondido por el kevin cline 06.07.2011 - 22:34
10

El problema típico planteado para la concatenación de cadenas gira en torno a algunos problemas:

  1. el símbolo + está sobrecargado
  2. errores simples
  3. los programadores son perezosos

# 1

El primer y más importante problema con el uso de + para la concatenación de cadenas y además es que estás usando + para la concatenación de cadenas y adición.

si tiene las variables a y b , y establece c = a + b , existe una ambigüedad que depende de los tipos de a y b . Esta ambigüedad te obliga a tomar medidas adicionales para mitigar el problema:

Concat de cadena:

c = '' + a + b;

Adición:

c = parseFloat(a) + parseFloat(b);

Esto me lleva a mi segundo punto

# 2

Es muy fácil convertir accidentalmente una variable en una cadena sin darse cuenta. También es fácil olvidar que su entrada viene como una cadena:

a = prompt('Pick a number');
b = prompt('Pick a second number');
alert( a + b );

Producirá resultados no intuitivos porque la solicitud devuelve el valor de cadena de la entrada.

# 3

La necesidad de escribir parseFloat o Number() cada vez que quiero hacer una adición es tediosa y molesta. Me considero lo suficientemente inteligente como para recordar no estropear mis tipos dinámicos, pero eso no significa que nunca haya arruinado mis tipos dinámicos . La verdad del asunto es que soy demasiado perezoso para escribir parseFloat o Number() cada vez que lo hago, porque hago mucho de adición.

¿Solución?

No todos los idiomas usan + para la concatenación de cadenas. PHP usa . para concatenar cadenas, lo que ayuda a distinguir cuándo desea agregar números y cuándo desea unir cadenas.

Se podría usar cualquier símbolo para concatenar cadenas, pero la mayoría ya está en uso, y es mejor evitar la duplicación. Si tuviera mi camino, probablemente usaría _ para unir cadenas y no permitiría _ en los nombres de variable.

    
respondido por el zzzzBov 07.07.2011 - 00:35

Lea otras preguntas en las etiquetas