Object.freeze () vs const

136

Object.freeze()parece un método de conveniencia de transición para avanzar hacia el uso consten ES6.

¿Hay casos en que ambos toman su lugar en el código o hay una forma preferida de trabajar con datos inmutables?

¿Debo usar Object.freeze()hasta el momento en que todos los navegadores con los que trabajo sean compatibles y constluego cambiar a usar const?

Sergei Basharov
fuente
2
He empezado a usar babeljs en mi proceso de construcción, por lo que puedo ignorar principalmente problemas de compatibilidad como estos.
gastador
22
No, hacen cosas diferentes. const evita la reasignación (por ejemplo, no puede const x = 1; x = 2); congelar evita la mutación (por ejemplo, no puede Object.freeze (x); xa = 2);
Joe
No estoy seguro de si tiene sentido hacer de esta una nueva pregunta o simplemente abordarla aquí, pero también me gustaría saber si existen grandes diferencias entre Symbols y Object.freeze. Siento que también están relacionados (es decir, los símbolos se evalúan como congelados, Object.isFrozenpero también son su propio tipo de datos primitivos ...)
agosto
1
La mutación se evita solo para el primer nivel, por lo que no puede Object.freeze (x); xa = 2, pero PUEDES Object.freeze (x); xab = 2. Ver jsfiddle.net/antimojv/op6ea91w/8 . Para una congelación completa, use bibliotecas ad hoc
Antimo

Respuestas:

232

consty Object.freezeson dos cosas completamente diferentes.

constse aplica a los enlaces ("variables"). Crea un enlace inmutable, es decir, no puede asignar un nuevo valor al enlace.

Object.freezetrabaja en valores , y más específicamente, valores de objetos . Hace que un objeto sea inmutable, es decir, no puede cambiar sus propiedades.

Felix Kling
fuente
3
Básicamente, constes lo nuevo var; solo tiene un alcance de bloque y evita la reasignación. Puede usar let, pero realmente solo necesita hacerlo si va a cambiar el valor al que apunta una variable, lo que tiene sentido para las variables de control / iterador de bucle y tipos simples como números y cadenas, pero no para la mayoría de los usos de objetos (incluidos matrices). Si desea un objeto / matriz cuyo contenido no se puede cambiar, entonces, además de declararlo, consttambién debe invocarlo Object.freeze().
Mark Reed
2
constNO es lo nuevo var, letes lo nuevovar
Facundo Colombier
84

En ES5 Object.freezeno funciona en primitivas, que probablemente se declararían más comúnmente constque los objetos. Puede congelar primitivas en ES6, pero luego también tiene soporte para const.

Por otro lado, constpara declarar objetos no los "congela", simplemente no puede volver a declarar todo el objeto, pero puede modificar sus claves libremente. Por otro lado, puedes redeclarar objetos congelados.

Object.freeze también es poco profundo, por lo que deberá aplicarlo recursivamente en objetos anidados para protegerlos.

var ob1 = {
   foo : 1,
    bar : {
        value : 2   
    }
};
Object.freeze( ob1 );

const ob2 = {
   foo : 1,
    bar : {
        value : 2   
    }
}

ob1.foo = 4;  // (frozen) ob1.foo not modified
ob2.foo = 4;  // (const) ob2.foo modified

ob1.bar.value = 4;  // (frozen) modified, because ob1.bar is nested
ob2.bar.value = 4;  // (const) modified

ob1.bar = 4;  // (frozen) not modified, bar is a key of obj1
ob2.bar = 4;  // (const) modified

ob1 = {};  // (frozen) ob1 redeclared
ob2 = {}; // (const) ob2 not redeclared
pawel
fuente
¡Esta explicación despejó muchas de mis preguntas de una sola vez! En cuanto a ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: ¿Es por el alcance del método?
Código Y
14

Resumen:

consty Object.freeze()sirven para propósitos totalmente diferentes.

  • constestá ahí para declarar una variable que debe ser asignada de inmediato y no puede ser reasignada. las variables declaradas por constson de ámbito de bloque y no de ámbito de función como las variables declaradas convar
  • Object.freeze()es un método que acepta un objeto y devuelve el mismo objeto. Ahora al objeto no se le puede quitar ninguna de sus propiedades o agregar nuevas propiedades.

Ejemplos const:

Ejemplo 1: no se puede reasignar const

const foo = 5;

foo = 6;

El siguiente código arroja un error porque estamos tratando de reasignar la variable foo que fue declarada con la constpalabra clave, no podemos reasignarla.

Ejemplo 2: las estructuras de datos que se asignan constpueden mutarse

const object = {
  prop1: 1,
  prop2: 2 
}

object.prop1 = 5;   // object is still mutable!
object.prop3 = 3;   // object is still mutable!

console.log(object);  // object is mutated

En este ejemplo, declaramos una variable usando la constpalabra clave y le asignamos un objeto. Aunque no podemos reasignar a esta variable llamada objeto, podemos mutar el objeto en sí. Si cambiamos las propiedades existentes o agregamos nuevas propiedades, esto tendrá efecto. Para deshabilitar cualquier cambio en el objeto que necesitamos Object.freeze().

Ejemplos Object.freeze():

Ejemplo 1: no se puede mutar un objeto congelado

object1 = {
  prop1: 1,
  prop2: 2
}

object2 = Object.freeze(object1);

console.log(object1 === object2); // both objects are refer to the same instance

object2.prop3 = 3; // no new property can be added, won't work

delete object2.prop1; // no property can be deleted, won't work

console.log(object2); // object unchanged

En este ejemplo, cuando llamamos Object.freeze()y damos object1como argumento, la función devuelve el objeto que ahora está 'congelado'. Si comparamos la referencia del nuevo objeto con el antiguo usando el ===operador, podemos observar que se refieren al mismo objeto. Además, cuando intentamos agregar o eliminar propiedades, podemos ver que esto no tiene ningún efecto (arrojará un error en modo estricto).

Ejemplo 2: los objetos con referencias no están completamente congelados

const object = {
  prop1: 1,
  nestedObj: {
    nestedProp1: 1,
    nestedProp2: 2,
  } 
}


const frozen = Object.freeze(object);

frozen.prop1 = 5; // won't have any effect
frozen.nestedObj.nestedProp1 = 5; //will update because the nestedObject isn't frozen

console.log(frozen);

Este ejemplo muestra que las propiedades de los objetos anidados (y otros por estructuras de datos de referencia) siguen siendo mutables . Por Object.freeze()lo tanto , no 'congela' completamente el objeto cuando tiene propiedades que son referencias (por ejemplo, matrices, objetos).

Willem van der Veen
fuente
12
var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields

El ejemplo anterior hace que su objeto sea completamente inmutable.

Veamos el siguiente ejemplo.

const obj = {
  a: 1,
  b: 2
};
obj.a = 13; // You can change a field
obj.newField = 3; // You can assign new field.

No dará ningún error.

Pero si lo intentas así

const obj = {
      a: 1,
      b: 2
    };
obj = {
 t:4
};

Lanzará un error como ese "obj es de solo lectura".

Otro caso de uso

const obj = {a:1};
var obj = 3;

Arrojará Duplicate declaration "obj"

También de acuerdo con la explicación de Mozilla docs const

La declaración const crea una referencia de solo lectura a un valor. No significa que el valor que posee es inmutable , solo que el identificador de variable no se puede reasignar.

Estos ejemplos creados de acuerdo con las características de babeljs ES6.

İlker Korkut
fuente
4

Deja que sea simple.

Ellos son diferentes. Verifique los comentarios en el código, eso explicará cada caso.

Const- Es una variable de alcance de bloque como let, cuyo valor no se puede reasignar, volver a declarar.

Eso significa

{
 const val = 10;  // you can not access it outside this block, block scope variable

}

console.log(val); // undefined because it is block scope 

const constvalue = 1;
constvalue = 2; // will give error as we are re-assigning the value;
const obj = { a:1 , b:2};

obj.a = 3;
obj.c = 4;
console.log(obj); // obj = {a:3,b:2,c:4} we are not assigning the value of identifier we can 
                  // change the object properties, const applied only on value, not with properties
obj = {x:1};     // error you are re-assigning the value of constant obj 
obj.a = 2 ;     // you can add, delete element of object

Todo el entendimiento es que const es un alcance de bloque y su valor no se reasigna.

Object.freeze: Las propiedades de la raíz del objeto no se pueden cambiar, tampoco podemos agregar y eliminar más propiedades, pero podemos reasignar todo el objeto nuevamente.

var x = Object.freeze({data:1,
    name:{
    firstname:"hero", lastname:"nolast"
    }
});

x.data = 12;  // the object properties can not be change but in const you can do
x.firstname ="adasd"; // you can not add new properties to object but in const you can do

x.name.firstname = "dashdjkha"; // The nested value are changeable 

//The thing you can do in Object.freeze but not in const

x = { a: 1};  // you can reassign the object when it is Object.freeze but const its not allowed

// Una cosa que es similar en ambos es que los objetos anidados son cambiables

const obj1 = {nested :{a:10}};
var obj2 =  Object.freeze({nested :{a:10}});

obj1.nested.a = 20; // both statement works
obj2.nested.a = 20;

Gracias.

Himanshu Sharma
fuente