¿Por qué puedo cambiar un objeto constante en JavaScript?
Sé que ES6 aún no está estandarizado, pero actualmente muchos navegadores lo admiten. const
palabras clave en JS.
En especificaciones, está escrito que:
El valor de una constante no puede cambiar mediante la reasignación y una constante no se puede volver a declarar. Por esto, aunque es posible declarar una constante sin inicializarla, sería inútil hacerlo.
y cuando hago algo como esto:
const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
Veo que todo está bien: xxx
está quieto 6
y yyy
está[]
.
Pero si lo hago yyy.push(6); yyy.push(1);
, mi matriz constante ha cambiado. Ahora mismo lo es [6, 1]
y por cierto todavía no puedo cambiarlo conyyy = 1;
.
¿Es esto un error o me falta algo? Lo probé en la última versión de Chrome y FF29.
La documentación de MDN dice:
...la constante no puede cambiar mediante reasignación
...la constante no puede volver a declararse
Cuando agrega una matriz u objeto, no reasigna ni declara la constante; ya está declarado y asignado. Simplemente estás agregando a la lista de elementos o propiedades a las que apunta la constante.
Entonces esto funciona bien:
const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
y esto:
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']
pero ninguno de estos:
const x = {};
x = {foo: 'bar'}; // error - re-assigning
const y = ['foo'];
const y = ['bar']; // error - re-declaring
const foo = 'bar';
foo = 'bar2'; // error - can not re-assign
var foo = 'bar3'; // error - already declared
function foo() {}; // error - already declared
Esto sucede porque su constante en realidad almacena una referencia a la matriz. Cuando unes algo a tu matriz no estás modificando tu valor constante, sino la matriz a la que apunta. Lo mismo sucedería si asignaras un objeto a una constante e intentaras modificar alguna de sus propiedades.
Si desea congelar una matriz u objeto para que no pueda modificarse, puede utilizar el Object.freeze
método, que ya forma parte de ECMAScript 5.
const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]