Por que + é tão ruim para concatenação?

44

Todo mundo continua dizendo que um dos problemas do JavaScript é usar + [ exemplo ] para concatenação de strings. Alguns dizem que o problema não é usar + , é coerção de tipo [veja os comentários do exemplo anterior]. Mas as linguagens strongmente tipadas usam + para tipos de concatenação e coerção sem nenhum problema. Por exemplo, em c #:

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

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

Então, por que a concatenação de strings em JavaScript é um problema tão grande?

    
por configurator 06.07.2011 / 21:20
fonte

4 respostas

68

Considere esta parte do código JavaScript:

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

Isso será registrado

result is 1020

O mais provável é que não seja o que se pretendia e pode ser difícil controlar o bug.

    
por 06.07.2011 / 21:59
fonte
41

Quando você diz "ruim", quer dizer "incorreto" ou "lento"? O argumento sobre o uso de operadores matemáticos para fazer concatenação de strings é discutivelmente um argumento "incorreto", mas também há um argumento a ser feito que usar + para fazer muito de concatenação de strings pode ser muito lento.

Não estamos falando de "Hello" + number quando falamos sobre desempenho, estamos falando de criar uma string relativamente grande anexando-a repetidamente em um loop.

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

Em JavaScript (e C #), as strings são imutáveis. Eles nunca podem ser alterados, apenas substituídos por outras strings. Você provavelmente está ciente de que combined + "hello " não modifica diretamente a variável combined - a operação cria uma nova sequência que é o resultado da concatenação das duas cadeias juntas, mas você deve então atribuir essa nova sequência à combined variável se você quiser que ela seja alterada.

Então, o que esse loop está fazendo é criar um milhão de objetos de string diferentes e jogar fora 999.999 deles. Criar tantas cadeias que estão crescendo continuamente em tamanho não é rápido, e agora o coletor de lixo tem muito trabalho a fazer para limpar depois disso.

O C # tem exatamente o mesmo problema, que é resolvido nesse ambiente pelo StringBuilder classe. Em JavaScript, você obterá um desempenho muito melhor construindo uma matriz de todas as cadeias que deseja concatenar e juntando-as uma vez no final, em vez de um milhão de vezes no loop:

var parts = [];
for (var i = 0; i < 1000000; i++) {
    parts.push("hello");
}
var combined = parts.join(" ");
    
por 06.07.2011 / 22:14
fonte
14

Não é ruim usar + para adição e concatenação, contanto que você só possa adicionar números e concatenar strings. No entanto, o Javascript converterá automaticamente entre números e strings conforme necessário, então você tem:

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

Talvez mais simplesmente, sobrecarregar "+" na presença de conversão automática de tipo rompe a associação esperada do operador +:

("x" + 1) + 3 != "x" + (1 + 3)
    
por 06.07.2011 / 22:34
fonte
10

O problema típico criado para a concatenação de strings gira em torno de alguns problemas:

  1. o símbolo + está sobrecarregado
  2. erros simples
  3. programadores sendo preguiçosos

# 1

O primeiro e mais importante problema com o uso de + para adição de e de concatenação de string é que você está usando + para concatenação de strings e

se você tiver as variáveis a e b e você definir c = a + b , haverá uma ambigüidade dependente dos tipos de a e b . Essa ambigüidade força você a tomar medidas extras para atenuar o problema:

String Concat:

c = '' + a + b;

Adição:

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

Isso me leva ao segundo ponto

# 2

É muito fácil converter acidentalmente uma variável em uma string sem perceber. Também é fácil esquecer que sua entrada está chegando como uma string:

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

Produzirá resultados não intuitivos porque o prompt retornará o valor da string da entrada.

# 3

Precisar digitar parseFloat ou Number() toda vez que eu quiser fazer uma adição é entediante e chato. Eu me considero inteligente o suficiente para lembrar de não estragar meus tipos dinâmicos, mas isso não significa que eu nunca estraguei meus tipos dinâmicos . A verdade é que estou com preguiça de digitar parseFloat ou Number() toda vez que faço uma adição, porque eu faço muito de adição.

Solução?

Nem todas as linguagens usam + para concatenação de strings. O PHP usa . para concatenar strings, o que ajuda a distinguir entre quando você deseja adicionar números e quando deseja unir strings.

Qualquer símbolo pode ser usado para concatenar strings, mas a maioria já é usada, e é melhor evitar a duplicação. Se eu fosse do meu jeito, provavelmente usaria _ para unir strings e não permitiria o _ em nomes de variáveis.

    
por 07.07.2011 / 00:35
fonte

Tags