Perché + è così male per la concatenazione?

44

Tutti continuano a dire che uno dei problemi di JavaScript sta usando + [ esempio ] per la concatenazione di stringhe. Alcuni dicono che il problema non sta usando + , è tipo coercizione [vedi i commenti dell'esempio precedente]. Ma le lingue strongmente tipizzate usano + per i tipi di concatenazione e coercizione senza alcun problema. Ad esempio, in C #:

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

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

Quindi perché la concatenazione di stringhe in JavaScript è un problema così grande?

    
posta configurator 06.07.2011 - 21:20
fonte

4 risposte

68

Considera questo pezzo di codice JavaScript:

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

Questo registrerà

result is 1020

Che molto probabilmente non è ciò che è stato previsto, e può essere un bug difficile da tracciare.

    
risposta data 06.07.2011 - 21:59
fonte
41

Quando dici "cattivo" intendi "errato" o intendi "lento"? L'argomento sull'utilizzo di operatori matematici per eseguire concatenazioni di stringhe è probabilmente un argomento "errato", ma c'è anche un argomento da sostenere che l'utilizzo di + per eseguire molto di concatenazione di stringhe può essere molto lento.

Non parliamo di "Hello" + number quando parliamo di prestazioni, stiamo parlando di creare una stringa relativamente grande aggiungendola ripetutamente in un ciclo.

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

In JavaScript (e C # per quella materia) le stringhe sono immutabili. Non possono mai essere cambiati, solo sostituiti con altre stringhe. Probabilmente sei consapevole del fatto che combined + "hello " non modifica direttamente la variabile combined - l'operazione crea una nuova stringa che è il risultato della concatenazione delle due stringhe insieme, ma devi quindi assegnare quella nuova stringa a combined variabile se vuoi che sia cambiato.

Quindi ciò che sta facendo questo ciclo è la creazione di un milione di oggetti stringa diversi e il lancio di 999.999 di essi. La creazione di molte stringhe che aumentano continuamente di dimensioni non è veloce, e ora il garbage collector ha molto lavoro da fare per pulire dopo questo.

C # ha lo stesso identico problema, risolto in quell'ambiente dal StringBuilder classe. In JavaScript, otterrai prestazioni molto migliori costruendo un array di tutte le stringhe che vuoi concatenare, e poi unendole insieme una volta alla fine, invece di un milione di volte nel ciclo:

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

Non è male usare + sia per l'aggiunta che per la concatenazione, purché sia possibile aggiungere solo numeri e concatenare solo stringhe. Tuttavia, Javascript converte automaticamente tra numeri e stringhe in base alle necessità, quindi hai:

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

Forse più semplicemente, sovraccaricare "+" in presenza della conversione automatica dei tipi interrompe l'associatività prevista dell'operatore +:

("x" + 1) + 3 != "x" + (1 + 3)
    
risposta data 06.07.2011 - 22:34
fonte
10

Il tipico problema sollevato per la concatenazione di stringhe ruota attorno ad alcuni problemi:

  1. il simbolo + viene sovraccaricato
  2. semplici errori
  3. i programmatori sono pigri

# 1

Il primo e più importante problema con l'utilizzo di + per la concatenazione di stringhe e è che stai usando + per la concatenazione di stringhe e aggiunta.

se hai le variabili a e b e imposti c = a + b , esiste un'ambiguità dipendente dai tipi di a e b . Questa ambiguità ti costringe a prendere ulteriori provvedimenti per mitigare il problema:

String Concat:

c = '' + a + b;

Aggiunta:

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

Questo mi porta al secondo punto

# 2

È molto facile lanciare accidentalmente una variabile su una stringa senza rendersene conto. È anche facile dimenticare che il tuo input sta entrando come una stringa:

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

Produrrà risultati non intuitivi perché prompt restituisce il valore stringa dell'input.

# 3

La necessità di digitare parseFloat o Number() ogni volta che voglio aggiungere è noioso e noioso. Mi considero abbastanza intelligente da ricordare di non rovinare i miei tipi dinamici, ma che non significa che non ho mai incasinato i miei tipi dinamici . La verità è che sono troppo pigro per digitare parseFloat o Number() ogni volta che aggiungo, perché faccio molto di addizione.

Soluzione?

Non tutte le lingue utilizzano + per la concatenazione di stringhe. PHP usa . per concatenare le stringhe, il che aiuta a distinguere tra quando vuoi aggiungere numeri e quando vuoi unire le stringhe.

È possibile utilizzare qualsiasi simbolo per concatenare stringhe, ma la maggior parte è già utilizzata ed è consigliabile evitare la duplicazione. Se avessi la mia strada, probabilmente userei _ per unire le stringhe e non consentire il _ nei nomi delle variabili.

    
risposta data 07.07.2011 - 00:35
fonte

Leggi altre domande sui tag