La palabra clave 'const' no hace que el valor sea inmutable. Qué significa eso?

85

Existe la definición constante en Exploring ES6 por el Dr. Axel Rauschmayer:

constfunciona como let, pero la variable que declara debe inicializarse inmediatamente, con un valor que no se puede cambiar posteriormente . […]

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

y luego escribe

Dificultad: la constante no hace que el valor sea inmutable

const solo significa que una variable siempre tiene el mismo valor, pero no significa que el valor en sí sea o se vuelva inmutable.

Estoy un poco confundido con este error. ¿Alguien puede definir claramente el constcon esta trampa?

Mukund Kumar
fuente
38
La explicación de MDN es clara: "La declaración const crea una referencia de solo lectura a un valor. No significa que el valor que contiene sea inmutable, solo que el identificador de la variable no se puede reasignar. Por ejemplo, en caso de que el contenido sea un objeto , esto significa que el objeto en sí puede modificarse ". (énfasis mío)
Gerardo Furtado
4
Significa que si el valor es mutable (por ejemplo, si es un objeto), aún puede mutar ese objeto (por ejemplo, actualizar, agregar, eliminar propiedades).
Felix Kling
2
const x = "immutable"es inmutable, porque Stringes inmutable. constprohíbe la mera reasignación.
3
@ibrahimmahrir: pasar una referencia (lo que hace JavaScript para los objetos) no es lo mismo que pasar por referencia (que describe la relación entre enlaces, el valor es irrelevante).
Felix Kling
2
@ibrahimmahrir: Sí, ese es el problema. El término pasar por referencia tiene un significado muy específico .
Felix Kling

Respuestas:

97

MDN lo resume muy bien:

La declaración const crea una referencia de solo lectura a un valor. No significa que el valor que tiene sea inmutable, solo que el identificador de variable no puede reasignarse. Por ejemplo, en caso de que el contenido sea un objeto, esto significa que el objeto en sí aún puede modificarse.

Más sucintamente: const crea una unión inmutable.

En otras palabras: const, como var, te da una parte mutable de memoria en la que estás almacenando algo. Sin embargo, const dicta que debe seguir refiriéndose a ese mismo fragmento de memoria; no puede reasignar la variable a un fragmento de memoria diferente, porque la referencia de variable es constante.

Para hacer algo realmente constante e inmutable después de haberlo declarado, necesita usar algo como Object.freeze(). Sin embargo, eso es superficial y solo funciona en pares clave / valor. Congelar un objeto completo requiere un poco más de esfuerzo. Hacerlo repetidamente de manera eficaz es aún más desafiante. Si realmente lo necesita, le recomiendo que consulte algo como Immutable.js

Mike Post
fuente
20
En términos de C: si una normal var xes a struct Object *x, a const xes a struct Object *const x. El puntero no se puede cambiar; la cosa a la que apunta puede.
Financia la demanda de Monica el
151

Cuando crea algo consten JavaScript, no puede reasignar la variable en sí para hacer referencia a otra cosa. Sin embargo, la variable aún puede hacer referencia a un objeto mutable.

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;

En el caso de primitivas como cadenas y números, constes más sencillo de entender, ya que no se mutan los valores sino que se asigna un nuevo valor a la variable.

Gomita de caramelo
fuente
18
Esta respuesta es mucho mejor que la aceptada. Más conciso y contiene código de ejemplo real. (En otras palabras, va al grano .) +1
jpmc26
16

Rebinding

consty las letdeclaraciones controlan si se permiten las reasignaciones (también conocidas como reasignaciones) entre identificadores y valores:

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);

Inmutabilidad

La inmutabilidad se controla a nivel de tipo. Objectes un tipo mutable, mientras que Stringes un tipo inmutable:

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


fuente
1

const significa: no puede cambiar el valor asignado inicialmente.

Primero, defina, qué es un valor en js. El valor puede ser: booleanos, cadenas, números, objetos, funciones y valores indefinidos.

Como: La gente te llama con tu nombre, no cambia. Sin embargo, te cambias de ropa. El vínculo entre la gente y usted es su nombre. El resto puede cambiar. Perdón por el extraño ejemplo.

Entonces, déjame darte algunos ejemplos:

// 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

Como puede ver, a menos que no esté cambiando el "primer" valor asignado a una constante, no hay error. Cada vez que intenta cambiar el primer valor asignado a otra cosa, se enoja y da un error.

Entonces, esto es lo segundo que puede saber al usar const. Es decir, debe inicializarse a un valor en su declaración o se enojará.

const orphan;                    // error
const rich = 0;                  // no error
Inanc Gumus
fuente
0

ES6/ ES2015 constpalabra clave:

La constpalabra clave se usa para declarar una variable de ámbito de bloque (como declarar con let). La diferencia entre declarar una variable con consty letes la siguiente:

  1. Una variable declarada constno se puede reasignar .
  2. Una variable declarada con constdebe asignarse cuando se declara . Esta es una consecuencia lógica del punto anterior porque una variable declarada con constno se puede reasignar, por eso tenemos que asignarla exactamente una vez cuando declaramos la variable .

Ejemplo:

// 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;

En el ejemplo anterior podemos observar lo siguiente:

  1. La variable myVariabledeclarada con letprimero puede declararse y luego asignarse.
  2. La variable myConstantdeclarada con constdebe declararse y asignarse al mismo tiempo.
  3. Cuando intentamos reasignar la variable myConstantobtenemos el siguiente error:

Error de tipo no detectado: asignación a variable constante

Advertencia: la variable asignada con constsigue siendo mutable:

Una variable declarada con constsimplemente no se puede reasignar, sigue siendo mutable . Ser mutable significa que la estructura de datos (objeto, matriz, mapa, etc.) que se asignó a la constvariable aún puede modificarse (es decir, mutar). Ejemplos de mutación son:

  1. Agregar / eliminar / alterar una propiedad de un objeto
  2. Cambiar el valor de una matriz en un índice de matriz específico

Si realmente desea que un objeto no sea mutable, tendrá que usar algo como Object.freeze(). Este es un método que congela un objeto. Un objeto congelado ya no se puede cambiar y no se pueden agregar nuevas propiedades.

Ejemplo:

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);

Willem van der Veen
fuente