Object.freeze () vs const


136

Object.freeze()sembra un metodo di praticità di transizione per passare all'utilizzo constin ES6.

Ci sono casi in cui entrambi prendono il loro posto nel codice o esiste un modo preferito di lavorare con dati immutabili?

Dovrei usare Object.freeze()fino al momento in cui tutti i browser con cui lavoro sono supportati constquindi passare a usare constinvece?


2
Ho iniziato ad usare babeljs nel mio processo di compilazione in modo da poter ignorare principalmente problemi di compatibilità come questi.
spender

22
No, fanno cose diverse. const impedisce la riassegnazione (ad es. non puoi const x = 1; x = 2); il congelamento impedisce la mutazione (ad es. non è possibile Object.freeze (x); xa = 2);
joews

Non sei sicuro che abbia senso trasformare questa domanda in una nuova domanda o affrontarla qui, ma sarei anche curioso di sapere se ci sono grandi differenze tra Symbols e Object.freeze? Sento che sono anche correlati (ovvero i simboli vengono valutati come congelati Object.isFrozenma sono anche il loro tipo di dati primitivo ...)
agosto

1
La mutazione è prevenuta solo per il primo livello, quindi non puoi Object.freeze (x); xa = 2, ma PUOI Object.freeze (x); xab = 2. Vedi jsfiddle.net/antimojv/op6ea91w/8 . Per un congelamento completo utilizzare le librerie ad hoc
Antimo

Risposte:


232

conste Object.freezesono due cose completamente diverse.

constsi applica ai binding ("variabili"). Crea un'associazione immutabile, ovvero non è possibile assegnare un nuovo valore all'associazione.

Object.freezefunziona sui valori e, più specificamente, sui valori degli oggetti . Rende immutabile un oggetto, cioè non è possibile modificarne le proprietà.


3
Fondamentalmente, constè il nuovo var; è solo a blocchi e impedisce la riassegnazione. È possibile utilizzare let, ma è necessario solo se si intende modificare il valore a cui punta una variabile, il che ha senso per le variabili di controllo / iteratore del ciclo e tipi semplici come numeri e stringhe, ma non per la maggior parte degli usi degli oggetti (incluso array). Se vuoi un oggetto / array il cui contenuto non può essere modificato, oltre a dichiararlo con constte dovresti anche chiamarlo Object.freeze().
Mark Reed,

2
constNON è il nuovo var, letè il nuovovar
Facundo Colombier,

84

In ES5 Object.freezenon funziona con le primitive, che verrebbero probabilmente più comunemente dichiarate usando constdegli oggetti. Puoi congelare le primitive in ES6, ma poi hai anche il supporto per const.

D'altra parte, constusato per dichiarare gli oggetti non li "congela", non puoi semplicemente dichiarare l'intero oggetto, ma puoi modificarne liberamente le chiavi. D'altra parte è possibile dichiarare oggetti congelati.

Object.freeze è anche superficiale, quindi è necessario applicarlo in modo ricorsivo su oggetti nidificati per proteggerli.

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

Questa spiegazione ha chiarito così tante delle mie domande in un colpo solo! Riguardo ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: è a causa dell'ambito del metodo?
YCode

14

Sommario:

conste Object.freeze()servono scopi totalmente diversi.

  • constè lì per dichiarare una variabile che deve essere valutata immediatamente e non può essere riassegnata. le variabili dichiarate constsono nell'ambito del blocco e non funzionano come le variabili dichiarate convar
  • Object.freeze()è un metodo che accetta un oggetto e restituisce lo stesso oggetto. Ora non è possibile rimuovere nessuna delle proprietà dell'oggetto o aggiungere nuove proprietà.

Esempi const:

Esempio 1: impossibile riassegnare const

const foo = 5;

foo = 6;

Il codice seguente genera un errore perché stiamo provando a riassegnare la variabile foo dichiarata con la constparola chiave, non possiamo riassegnarla.

Esempio 2: le strutture dati a cui sono assegnate constpossono essere mutate

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

In questo esempio dichiariamo una variabile usando la constparola chiave e gli assegniamo un oggetto. Sebbene non possiamo riassegnare questa variabile chiamata oggetto, possiamo mutare l'oggetto stesso. Se cambiamo le proprietà esistenti o aggiungiamo nuove proprietà, ciò avrà effetto. Per disabilitare eventuali modifiche all'oggetto di cui abbiamo bisogno Object.freeze().

Esempi Object.freeze():

Esempio 1: impossibile mutare un oggetto congelato

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

In questo esempio quando chiamiamo Object.freeze()e forniamo object1come argomento la funzione restituisce l'oggetto che ora è "congelato". Se confrontiamo il riferimento del nuovo oggetto con il vecchio oggetto usando l' ===operatore, possiamo osservare che si riferiscono allo stesso oggetto. Inoltre, quando proviamo ad aggiungere o rimuovere qualsiasi proprietà, possiamo vedere che ciò non ha alcun effetto (genererà un errore in modalità rigorosa).

Esempio 2: gli oggetti con riferimenti non sono completamente congelati

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

Questo esempio mostra che le proprietà degli oggetti nidificati (e altri per strutture di dati di riferimento) sono ancora modificabili . Quindi Object.freeze()non "congela" completamente l'oggetto quando ha proprietà che sono riferimenti (ad es. Array, oggetti).


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

L'esempio sopra rende completamente immutabile il tuo oggetto.

Diamo un'occhiata al seguente esempio.

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

Non darà alcun errore.

Ma se ci provi così

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

Verrà generato un errore del tipo "obj è di sola lettura".

Un altro caso d'uso

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

Lancerà Duplicate declaration "obj"

Anche secondo la spiegazione di const dei documenti di Mozilla

La dichiarazione const crea un riferimento di sola lettura a un valore. Non significa che il valore che detiene sia immutabile , ma solo che l'identificatore di variabile non può essere riassegnato.

Questo esempio è stato creato in base alle funzionalità di babeljs ES6.


4

Sia semplice.

Sono diversi. Controlla i commenti sul codice, che spiegheranno ogni caso.

Const- È una variabile dell'ambito del blocco come let, il cui valore non può essere riassegnato, ri-dichiarato.

Questo 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

L'intera comprensione è che const è un ambito di blocco e il suo valore non viene riassegnato.

Object.freeze: Le proprietà della radice dell'oggetto sono immutabili, inoltre non possiamo aggiungere ed eliminare più proprietà ma possiamo riassegnare nuovamente l'intero oggetto.

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 simile in entrambi è che l'oggetto nidificato è modificabile

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

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

Grazie.

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.