Object.freeze () vs const

136

Object.freeze()semble être une méthode de commodité de transition vers l'utilisation constdans ES6.

Existe-t-il des cas où les deux prennent leur place dans le code ou existe-t-il une manière préférée de travailler avec des données immuables?

Dois-je utiliser Object.freeze()jusqu'au moment où tous les navigateurs avec lesquels je travaille prend en charge constpuis passer à l'utilisation à la constplace?

Sergueï Basharov
la source
2
J'ai commencé à utiliser babeljs dans mon processus de construction afin que je puisse principalement ignorer les problèmes de compatibilité tels que ceux-ci.
dépenser
22
Non - ils font des choses différentes. const empêche la réaffectation (par exemple, vous ne pouvez pas const x = 1; x = 2); freeze empêche la mutation (par exemple, vous ne pouvez pas Object.freeze (x); xa = 2);
joews
Je ne sais pas si cela a du sens d'en faire une nouvelle question ou simplement de la clouer ici, mais je serais également curieux de savoir s'il existe de grandes différences entre Symbols et Object.freeze? Je pense qu'ils sont également liés (c'est-à-dire que les symboles sont évalués comme gelés, Object.isFrozenmais ils sont également leur propre type de données primitif ...)
août
1
La mutation n'est empêchée que pour le premier niveau donc vous ne pouvez pas Object.freeze (x); xa = 2, mais vous POUVEZ Object.freeze (x); xab = 2. Voir jsfiddle.net/antimojv/op6ea91w/8 . Pour un gel complet, utilisez les bibliothèques ad hoc
Antimo

Réponses:

232

constet Object.freezesont deux choses complètement différentes.

consts'applique aux liaisons ("variables"). Il crée une liaison immuable, c'est-à-dire que vous ne pouvez pas attribuer une nouvelle valeur à la liaison.

Object.freezetravaille sur les valeurs , et plus spécifiquement, les valeurs d'objet . Cela rend un objet immuable, c'est-à-dire que vous ne pouvez pas modifier ses propriétés.

Félix Kling
la source
3
Fondamentalement, constest le nouveau var; il est simplement limité et empêche la réaffectation. Vous pouvez l'utiliser let, mais vous n'en avez vraiment besoin que si vous voulez changer la valeur vers laquelle pointe une variable, ce qui est logique pour les variables de contrôle / itérateur de boucle et les types simples comme les nombres et les chaînes, mais pas pour la plupart des utilisations d'objets (y compris tableaux). Si vous voulez un objet / tableau dont le contenu ne peut pas être modifié, alors en plus de le déclarer avec, constvous devez également l'appeler Object.freeze().
Mark Reed
2
constn'est PAS le nouveau var, letest le nouveauvar
Facundo Colombier
84

Dans ES5 Object.freezene fonctionne pas sur les primitives, qui seraient probablement plus communément déclarées en utilisant constque les objets. Vous pouvez figer les primitives dans ES6, mais vous avez également la prise en charge de const.

D'un autre côté, constutilisé pour déclarer des objets ne les "gèle" pas, vous ne pouvez simplement pas redéclarer l'objet entier, mais vous pouvez modifier ses clés librement. D'autre part, vous pouvez redéclarer les objets gelés.

Object.freeze est également superficielle, vous devrez donc l'appliquer de manière récursive sur les objets imbriqués pour les protéger.

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
cliquet
la source
Cette explication a résolu tant de mes questions en un seul passage! Concernant ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: est-ce à cause de la portée de la méthode?
YCode
14

Résumé:

constet Object.freeze()servent des objectifs totalement différents.

  • constest là pour déclarer une variable qui doit être assinged tout de suite et ne peut pas être réaffectée. les variables déclarées par constont une portée de bloc et non une portée de fonction comme les variables déclarées avecvar
  • Object.freeze()est une méthode qui accepte un objet et renvoie le même objet. Désormais, l'objet ne peut avoir aucune de ses propriétés supprimées ni aucune nouvelle propriété ajoutée.

Exemples const:

Exemple 1: impossible de réaffecter const

const foo = 5;

foo = 6;

Le code suivant génère une erreur car nous essayons de réaffecter la variable foo qui a été déclarée avec le constmot clé, nous ne pouvons pas la réaffecter.

Exemple 2: les structures de données affectées constpeuvent être mutées

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

Dans cet exemple, nous déclarons une variable à l'aide du constmot - clé et lui affectons un objet. Bien que nous ne puissions pas réaffecter à cette variable appelée object, nous pouvons muter l'objet lui-même. Si nous modifions les propriétés existantes ou ajoutons de nouvelles propriétés, cela aura un effet. Pour désactiver toute modification de l'objet dont nous avons besoin Object.freeze().

Exemples Object.freeze():

Exemple 1: impossible de muter un objet figé

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

Dans cet exemple, lorsque nous appelons Object.freeze()et donnons object1comme argument, la fonction renvoie l'objet qui est maintenant «gelé». Si nous comparons la référence du nouvel objet à l'ancien objet à l'aide de l' ===opérateur, nous pouvons observer qu'ils font référence au même objet. De plus, lorsque nous essayons d'ajouter ou de supprimer des propriétés, nous pouvons voir que cela n'a aucun effet (générera une erreur en mode strict).

Exemple 2: les objets avec des références ne sont pas entièrement figés

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

Cet exemple montre que les propriétés des objets imbriqués (et d'autres structures de données de référence) sont toujours modifiables . Donc, Object.freeze()ne «fige» pas complètement l'objet quand il a des propriétés qui sont des références (par exemple à des tableaux, des objets).

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

L'exemple ci-dessus rend complètement votre objet immuable.

Regardons l'exemple suivant.

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

Cela ne donnera aucune erreur.

Mais si tu essaies comme ça

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

Il lancera une erreur comme celle-ci "obj est en lecture seule".

Un autre cas d'utilisation

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

Il jettera Duplicate declaration "obj"

Aussi selon Mozilla Docs Const Explication

La déclaration const crée une référence en lecture seule à une valeur. Cela ne signifie pas que la valeur qu'il contient est immuable , mais uniquement que l'identificateur de variable ne peut pas être réaffecté.

Ces exemples créés selon les fonctionnalités de babeljs ES6.

İlker Korkut
la source
4

Soyons simples.

Ils sont différents. Vérifiez les commentaires sur le code, cela expliquera chaque cas.

Const- C'est une variable de portée de bloc comme let, dont la valeur ne peut pas être réaffectée, re-déclarée.

Cela signifie

{
 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

La compréhension générale est que const est une portée de bloc et sa valeur n'est pas réaffectée.

Object.freeze: Les propriétés de la racine de l'objet ne sont pas modifiables, nous ne pouvons pas non plus ajouter et supprimer plus de propriétés mais nous pouvons réaffecter à nouveau l'objet entier.

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

// Une chose qui est similaire dans les deux est, les objets imbriqués sont modifiables

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

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

Merci.

Himanshu sharma
la source