Le stringhe JavaScript sono immutabili?Ho bisogno di un "costruttore di stringhe" in JavaScript?

StackOverflow https://stackoverflow.com/questions/51185

  •  09-06-2019
  •  | 
  •  

Domanda

Javascript utilizza stringhe immutabili o mutabili?Ho bisogno di un "costruttore di stringhe"?

È stato utile?

Soluzione

Sono immutabili.Non puoi modificare un carattere all'interno di una stringa con qualcosa di simile var myString = "abbdef"; myString[2] = 'c'.I metodi di manipolazione delle stringhe come trim, slice restituire nuove stringhe.

Allo stesso modo, se si hanno due riferimenti alla stessa stringa, la modifica di uno non influisce sull'altro

let a = b = "hello";
a = a + " world";
// b is not affected

Tuttavia, ho sempre sentito ciò che Ash ha menzionato nella sua risposta (che l'uso di Array.join è più veloce per la concatenazione), quindi ho voluto testare i diversi metodi di concatenazione delle stringhe e di astrazione nel modo più veloce in uno StringBuilder.Ho scritto alcuni test per vedere se questo è vero (non lo è!).

Questo era quello che credevo sarebbe stato il modo più veloce, anche se continuavo a pensare che l'aggiunta di una chiamata al metodo avrebbe potuto renderlo più lento...

function StringBuilder() {
    this._array = [];
    this._index = 0;
}

StringBuilder.prototype.append = function (str) {
    this._array[this._index] = str;
    this._index++;
}

StringBuilder.prototype.toString = function () {
    return this._array.join('');
}

Ecco i test di velocità delle prestazioni.Tutti e tre creano una gigantesca stringa composta da concatenazioni "Hello diggity dog" centomila volte in una stringa vuota.

Ho creato tre tipi di test

  • Utilizzando Array.push E Array.join
  • Usare l'indicizzazione degli array per evitare Array.push, quindi utilizzando Array.join
  • Concatenazione diretta di stringhe

Quindi ho creato gli stessi tre test astraendoli in StringBuilderConcat, StringBuilderArrayPush E StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5 Per favore, vai lì ed esegui i test in modo da poter ottenere un bel campione.Tieni presente che ho corretto un piccolo bug, quindi i dati per i test sono stati cancellati, aggiornerò la tabella una volta che ci saranno abbastanza dati sulle prestazioni.Vai a http://jsperf.com/string-concat-without-sringbuilder/5 per la vecchia tabella dati.

Ecco alcuni numeri (Ultimo aggiornamento di maggio 2018), se non vuoi seguire il link.Il numero su ciascun test è espresso in 1000 operazioni/secondo (Più alto è meglio)

| Browser          | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 71.0.3578 | 988   | 1006 | 2902   | 963     | 1008   | 2902     |
| Firefox 65       | 1979  | 1902 | 2197   | 1917    | 1873   | 1953     |
| Edge             | 593   | 373  | 952    | 361     | 415    | 444      |
| Exploder 11      | 655   | 532  | 761    | 537     | 567    | 387      |
| Opera 58.0.3135  | 1135  | 1200 | 4357   | 1137    | 1188   | 4294     | 

Risultati

  • Al giorno d'oggi, tutti i browser sempreverdi gestiscono bene la concatenazione di stringhe. Array.join aiuta solo IE 11

  • Nel complesso, Opera è più veloce, 4 volte più veloce di Array.join

  • Firefox è il secondo e Array.join è solo leggermente più lento in FF ma considerevolmente più lento (3x) in Chrome.

  • Chrome è terzo ma il concat di stringhe è 3 volte più veloce di Array.join

  • La creazione di uno StringBuilder sembra non influire troppo sulle prestazioni.

Spero che qualcun altro lo trovi utile

Caso di prova diverso

Poiché @RoyTinker pensava che il mio test fosse difettoso, ho creato un nuovo caso che non crea una stringa di grandi dimensioni concatenando la stessa stringa, ma utilizza un carattere diverso per ogni iterazione.La concatenazione delle stringhe sembrava ancora più veloce o altrettanto veloce.Facciamo eseguire quei test.

Suggerisco a tutti di continuare a pensare ad altri modi per testarlo e di sentirsi liberi di aggiungere nuovi collegamenti a diversi casi di test di seguito.

http://jsperf.com/string-concat-without-sringbuilder/7

Altri suggerimenti

dal libro sul rinoceronte:

In JavaScript, le stringhe sono oggetti immutabili, il che significa che i personaggi al suo interno potrebbero non essere modificati e che qualsiasi operazione sulle stringhe crei effettivamente nuove stringhe.Le stringhe sono assegnate per riferimento, non per valore.In generale, quando un oggetto viene assegnato per riferimento, una modifica apportata all'oggetto tramite un riferimento sarà visibile attraverso tutti gli altri riferimenti all'oggetto.Poiché le stringhe non possono essere modificate, tuttavia, è possibile avere più riferimenti a un oggetto stringa e non preoccuparti che il valore della stringa cambierà senza che tu lo sappia

Suggerimento per le prestazioni:

Se devi concatenare stringhe di grandi dimensioni, inserisci le parti della stringa in un array e utilizza il file Array.Join() metodo per ottenere la stringa complessiva.Questo può essere molte volte più veloce per concatenare un gran numero di stringhe.

Non c'è StringBuilder in JavaScript.

Le stringhe sono immutabili – non possono cambiare, possiamo solo creare nuove corde.

Esempio:

var str= "Immutable value"; // it is immutable

var other= statement.slice(2, 10); // new string

Il valore del tipo di stringa è immutabile, Ma l'oggetto String, che viene creato utilizzando il costruttore String(), è mutabile, perché è un oggetto e puoi aggiungergli nuove proprietà.

> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }

Nel frattempo, sebbene sia possibile aggiungere nuove proprietà, non è possibile modificare quelle già esistenti

Uno screenshot di un test nella console Chrome

In conclusione, 1.tutto il valore del tipo di stringa (tipo primitivo) è immutabile.2.L'oggetto String è mutabile, ma il valore del tipo stringa (tipo primitivo) che contiene è immutabile.

Giusto per chiarire per menti semplici come la mia (da MDN):

Gli immutabili sono gli oggetti il ​​cui stato non può essere modificato una volta creato l'oggetto.

Stringhe e numeri sono immutabili.

Immutabile significa che:

È possibile fare in modo che il nome di una variabile punti a un nuovo valore, ma il valore precedente viene ancora mantenuto in memoria.Da qui la necessità della raccolta differenziata.

var immutableString = "Hello";

// Nel codice precedente viene creato un nuovo oggetto con valore stringa.

immutableString = immutableString + "World";

// Ora stiamo aggiungendo "World" al valore esistente.

Sembra che stiamo modificando la stringa "immutableString", ma non è così.Invece:

Aggiungendo "immutableString" con un valore stringa, si verificano i seguenti eventi:

  1. Viene recuperato il valore esistente di "immutableString".
  2. "World" viene aggiunto al valore esistente di "immutableString"
  3. Il valore risultante viene quindi assegnato a un nuovo blocco di memoria
  4. L'oggetto "immutableString" ora punta allo spazio di memoria appena creato
  5. Lo spazio di memoria creato in precedenza è ora disponibile per la garbage collection.

Per quanto riguarda la tua domanda (nel tuo commento alla risposta di Ash) sullo StringBuilder in ASP.NET Ajax, gli esperti sembrano non essere d'accordo su questo.

Christian Wenz dice nel suo libro Programmazione ASP.NET AJAX (O'Reilly) che "questo approccio non ha alcun effetto misurabile sulla memoria (in effetti, l'implementazione sembra essere leggermente più lenta dell'approccio standard)."

D'altra parte Gallo et al dicono nel loro libro ASP.NET AJAX in azione (Manning) che "Quando il numero di stringhe da concatenare è maggiore, lo string builder diventa un oggetto essenziale per evitare enormi cali di prestazioni."

Immagino che dovresti fare il tuo benchmarking e i risultati potrebbero differire anche tra i browser.Tuttavia, anche se non migliora le prestazioni, potrebbe comunque essere considerato "utile" per i programmatori abituati a programmare con StringBuilders in linguaggi come C# o Java.

È un post in ritardo, ma non ho trovato una buona citazione di un libro tra le risposte.

Ecco un'eccezione definita da un libro affidabile:

Le stringhe sono immutabili in ECMAScript, il che significa che una volta create, i loro valori non possono cambiare.Per modificare la stringa contenuta in una variabile, la stringa originale deve essere distrutta e la variabile riempita con un'altra stringa contenente un nuovo valore... —JavaScript professionale per sviluppatori Web, 3a edizione, p.43

Ora, la risposta che cita l'estratto del libro di Rhino ha ragione sull'immutabilità delle stringhe ma che si dice che le stringhe sono assegnate per riferimento, non per valore ". (Probabilmente inizialmente intendevano mettere le parole in modo opposto).

L'equivoco "riferimento/valore" è chiarito nel capitolo "JavaScript professionale", intitolato "Valori primitivi e di riferimento":

I cinque tipi primitivi...[sono]:Non definito, Null, Booleano, Numero e Stringa.Si dice che queste variabili siano accessibili tramite valore, perché stai manipolando il valore effettivo memorizzato nella variabile. —JavaScript professionale per sviluppatori Web, 3a edizione, p.85

questo è contrario a oggetti:

Quando manipoli un oggetto, stai davvero lavorando su un riferimento a quell'oggetto piuttosto che sull'oggetto stesso.Per questo motivo si dice che tali valori sono accessibili tramite riferimento.—JavaScript professionale per sviluppatori Web, 3a edizione, p.85

Le stringhe JavaScript sono infatti immutabili.

Le stringhe in Javascript sono immutabili

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top