La parola chiave "const" non rende il valore immutabile. Cosa significa?


85

C'è la definizione const in Exploring ES6 del Dr. Axel Rauschmayer:

constfunziona come let, ma la variabile che dichiari deve essere inizializzata immediatamente, con un valore che non può essere modificato in seguito . [...]

const bar = 123;
bar = 456;  // TypeError: `bar` is read-only

e poi scrive

Trappola: const non rende il valore immutabile

const significa solo che una variabile ha sempre lo stesso valore, ma non significa che il valore stesso sia o diventi immutabile.

Sono poco confuso con questa trappola. Qualcuno può definire chiaramente il constcon questa trappola?


38
La spiegazione MDN è chiara: "La dichiarazione const crea un riferimento di sola lettura a un valore. Non significa che il valore che contiene è immutabile, ma solo che l'identificatore della variabile non può essere riassegnato. Ad esempio, nel caso in cui il contenuto sia un oggetto , questo significa che l'oggetto stesso può ancora essere modificato . " (enfasi mia)
Gerardo Furtado

4
Significa che se il valore è modificabile, (ad es. Se è un oggetto), puoi comunque mutare quell'oggetto (ad es. Aggiornare, aggiungere, rimuovere proprietà).
Felix Kling

2
const x = "immutable"è immutabile, perché Stringè immutabile. constvieta la semplice riassegnazione.

3
@ibrahimmahrir: passare un riferimento (cosa fa JavaScript per gli oggetti) non è la stessa cosa che passare per riferimento (che descrive la relazione tra le associazioni, il valore è irrilevante).
Felix Kling

2
@ibrahimmahrir: Sì, questo è il problema. Il termine pass-by-reference ha un significato molto specifico .
Felix Kling

Risposte:


97

MDN lo riassume bene:

La dichiarazione const crea un riferimento di sola lettura a un valore. Non significa che il valore che contiene sia immutabile, ma solo che l'identificatore della variabile non può essere riassegnato. Ad esempio, nel caso in cui il contenuto sia un oggetto, ciò significa che l'oggetto stesso può ancora essere modificato.

Più succintamente: const crea un'associazione immutabile.

In altre parole: const, come var, ti dà un pezzo mutevole di memoria in cui stai memorizzando qualcosa. Tuttavia, const impone che devi continuare a fare riferimento a quello stesso pezzo di memoria: non puoi riassegnare la variabile a un diverso pezzo di memoria, perché il riferimento alla variabile è costante.

Per creare davvero qualcosa di costante e immutabile dopo averlo dichiarato, devi usare qualcosa di simile Object.freeze(). Tuttavia, è superficiale e funziona solo su coppie chiave / valore. Il congelamento di un intero oggetto richiede un po 'più di sforzo. Farlo ripetutamente in modo performante è ancora più impegnativo. Se ne hai davvero bisogno, ti consiglio di dare un'occhiata a qualcosa come Immutable.js


20
In termini C: se un normale var xè a struct Object *x, a const xè a struct Object *const x. Il puntatore non può essere modificato; la cosa a cui punta può.
Finanzia la causa di Monica il

151

Quando crei qualcosa constin JavaScript, non puoi riassegnare la variabile stessa per fare riferimento a qualcos'altro. Tuttavia, la variabile può ancora fare riferimento a un oggetto modificabile.

const x = {a: 123};

// This is not allowed.  This would reassign `x` itself to refer to a
// different object.
x = {b: 456};

// This, however, is allowed.  This would mutate the object `x` refers to,
// but `x` itself hasn't been reassigned to refer to something else.
x.a = 456;

Nel caso di primitive come stringhe e numeri, constè più semplice da capire, poiché non si mutano i valori ma si assegna invece un nuovo valore alla variabile.


18
Questa risposta è molto migliore di quella accettata. Più succinto e contiene codice di esempio effettivo. (In altre parole, arriva al punto .) +1
jpmc26

16

Rebinding

conste le letdichiarazioni controllano se sono consentite riassegnazioni (note anche come riassegnazioni) tra identificatori e valori:

const x = "initial value";
let y = "initial value";

// rebinding/reassignment

try { x = "reassignment" } catch(e) { console.log(x) } // fails

y = "reassignment"; // succeeds
console.log(y);

Immutabilità

L'immutabilità è controllata a livello di tipo. Objectè un tipo mutabile, mentre Stringè un tipo immutabile:

const o = {mutable: true};
const x = "immutable";

// mutations

o.foo = true; // succeeds
x[0] = "I"; // fails

console.log(o); // {mutable: true, foo: true}
console.log(x); // immutable


1

const significa: non è possibile modificare il valore inizialmente assegnato.

Per prima cosa, definisci cos'è un valore in js. Il valore può essere: valori booleani, stringhe, numeri, oggetti, funzioni e valori indefiniti.

Tipo: le persone ti chiamano con il tuo nome, non cambia. Tuttavia, cambi i vestiti. Il legame tra le persone e te è il tuo nome. Il resto può cambiare. Ci scusiamo per lo strano esempio.

Quindi, lascia che ti dia alcuni esempi:

// boolean
const isItOn = true;
isItOn = false;           // error

// number
const counter = 0;
counter++;                // error

// string
const name = 'edison';
name = 'tesla';           // error

// objects
const fullname = {
  name: 'albert',
  lastname: 'einstein'
};

fullname = {              // error
  name: 'werner',
  lastname: 'heisenberg'
};
// NOW LOOK AT THIS:
//
// works because, you didn't change the "value" of fullname
// you changed the value inside of it!
fullname.name = 'hermann';

const increase = aNumber => ++aNumber;
increase = aNumber => aNumber + 1;      // error

// NOW LOOK AT THIS:
//
// no error because now you're not changing the value
// which is the decrease function itself. function is a
// value too.
let anotherNumber = 3;
const decrease = () => --anotherNumber;

anotherNumber = 10;             // no error
decrease();                     // outputs 9

const chaos = undefined;
chaos = 'let there be light'    // error

const weird = NaN;
weird = 0                       // error

Come puoi vedere, a meno che tu non stia cambiando il "primo" valore assegnato a una const, nessun errore. Ogni volta che provi a cambiare il primo valore assegnato a qualcos'altro, si arrabbia e dà un errore.

Quindi, questa è la seconda cosa che potresti sapere quando usi const. Cioè, dovrebbe essere inizializzato su un valore nella sua dichiarazione o sarà arrabbiato.

const orphan;                    // error
const rich = 0;                  // no error

0

ES6/ ES2015 constparola chiave:

La constparola chiave viene utilizzata per dichiarare una variabile con ambito di blocco (come dichiarare con let). La differenza tra la dichiarazione di una variabile con conste letè la seguente:

  1. Una variabile dichiarata constnon può essere riassegnata .
  2. Una variabile dichiarata con constdeve essere assegnata quando dichiarata . Questa è una logica conseguenza del punto precedente perché una variabile dichiarata con constnon può essere riassegnata, ecco perché dobbiamo assegnarla esattamente una volta quando dichiariamo la variabile .

Esempio:

// we declare variable myVariable
let myVariable;

// first assignment
myVariable = 'First assingment';
// additional assignment
myVariable = 'Second assignment';

// we have to declare AND initialize the variable at the same time
const myConstant = 3.14;

// This will throw an error
myConstant = 12;

Nell'esempio sopra possiamo osservare quanto segue:

  1. La variabile myVariabledichiarata con letpuò essere prima dichiarata e poi assegnata.
  2. La variabile myConstantdichiarata con constdeve essere dichiarata e assegnata contemporaneamente.
  3. Quando proviamo a riassegnare la variabile myConstantotteniamo il seguente errore:

Errore di tipo non rilevato: assegnazione a una variabile costante

Avvertenza: la variabile assegnata con const è ancora modificabile:

Una variabile dichiarata con constsemplicemente non può essere riassegnata, è ancora modificabile . Essere modificabile significa che la struttura dei dati (oggetto, array, mappa, ecc.) Assegnata alla constvariabile può ancora essere alterata (cioè mutata). Esempi di mutazione sono:

  1. Aggiunta / eliminazione / modifica di una proprietà di un oggetto
  2. Modifica del valore di un array in un indice di array specifico

Se vuoi davvero che un oggetto non sia mutabile, dovrai usare qualcosa di simile Object.freeze(). Questo è un metodo che congela un oggetto. Un oggetto congelato non può più essere modificato e non è possibile aggiungere nuove proprietà.

Esempio:

const obj = {prop1: 1};

obj.prop1 = 2;
obj.prop2 = 2;

console.log(obj);

// We freeze the object here
Object.freeze(obj);

obj.prop1 = 5;
delete obj.prop2;

// The object was frozen and thus not mutated
console.log(obj);

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.