Je viens d'entendre parler des méthodes JavaScript freeze
et seal
, qui peuvent être utilisées pour rendre n'importe quel objet immuable.
Voici un exemple court d'utilisation:
var o1 = {}, o2 = {};
Object.freeze(o2);
o1["a"] = "worked";
o2["a"] = "worked";
alert(o1["a"]); //prints "worked"
alert(o2["a"]); //prints "undefined"
Quelle est la différence entre freeze
et seal
? Peuvent-ils augmenter les performances?
delete
retournera falsewritable
et leur attribut value
si writeable
est vrai).TypeError
lors d'une tentative de modification de la valeur de l'objet scellé lui-même (le plus souvent en mode strict)Object.seal
fait, plus:Ni l'un ni l'autre n'affecte les objets "profonds"/petits-enfants. Par exemple, si obj
est gelé, obj.el
ne peut pas être réaffecté, mais la valeur de obj.el
pourrait être modifié, par exemple obj.el.id
peut être changé.
Le scellement ou le gel d’un objet peut affecter sa vitesse d’énumération, selon le navigateur:
Tests: objets scellés , objets gelés .
J'ai écrit un projet test qui compare ces 3 méthodes:
Object.freeze()
Object.seal()
Object.preventExtensions()
Mes tests unitaires couvrent les cas CRUD:
Résultat:
Object.freeze()
crée un objet gelé, ce qui signifie qu'il prend un objet existant et appelle essentiellement Object.seal()
, mais il marque également toutes les propriétés de “data accessor” comme étant writable:false
, de sorte que leurs valeurs ne peuvent pas être changées. - Kyle Simpson, vous ne savez pas JS - Prototypes This & Object
J'examinais les différences entre Freeze et Seal dans ECMAScript 5 et ai créé un script pour clarifier les différences. Gelé crée un objet immuable comprenant des données et une structure. Seal empêche les modifications apportées aux interfaces nommées - pas d’ajouts, de suppressions - mais vous pouvez muter l’objet et redéfinir la signification de son interface.
function run()
{
var myObject = function()
{
this.test = "testing";
}
//***************************SETUP****************************
var frozenObj = new myObject();
var sealedObj = new myObject();
var allFrozen = Object.freeze(frozenObj);
var allSealed = Object.seal(sealedObj);
alert("frozenObj of myObject type now frozen - Property test= " + frozenObj.test);
alert("sealedObj of myObject type now frozen - Property test= " + sealedObj.test);
//***************************FROZEN****************************
frozenObj.addedProperty = "added Property"; //ignores add
alert("Frozen addedProperty= " + frozenObj.addedProperty);
delete frozenObj.test; //ignores delete
alert("Frozen so deleted property still exists= " + frozenObj.test);
frozenObj.test = "Howdy"; //ignores update
alert("Frozen ignores update to value= " + frozenObj.test);
frozenObj.test = function() { return "function"; } //ignores
alert("Frozen so ignores redefinition of value= " + frozenObj.test);
alert("Is frozen " + Object.isFrozen(frozenObj));
alert("Is sealed " + Object.isSealed(frozenObj));
alert("Is extensible " + Object.isExtensible(frozenObj));
alert("Cannot unfreeze");
alert("result of freeze same as the original object: " + (frozenObj === allFrozen).toString());
alert("Date.now = " + Date.now());
//***************************SEALED****************************
sealedObj.addedProperty = "added Property"; //ignores add
alert("Sealed addedProperty= " + sealedObj.addedProperty);
sealedObj.test = "Howdy"; //allows update
alert("Sealed allows update to value unlike frozen= " + sealedObj.test);
sealedObj.test = function() { return "function"; } //allows
alert("Sealed allows redefinition of value unlike frozen= " + sealedObj.test);
delete sealedObj.test; //ignores delete
alert("Sealed so deleted property still exists= " + sealedObj.test);
alert("Is frozen " + Object.isFrozen(sealedObj));
alert("Is sealed " + Object.isSealed(sealedObj));
alert("Is extensible " + Object.isExtensible(sealedObj));
alert("Cannot unseal");
alert("result of seal same as the original object: " + (sealedObj === allSealed).toString());
alert("Date.now = " + Date.now());
}
Je sais que je peux être un peu en retard mais
false
. où comme dans Sealed accessible en écriture l'attribut est défini sur true
et le reste des attributs est faux.Vous pouvez maintenant forcer une propriété d'objet unique à être gelée au lieu de geler l'objet entier. Vous pouvez y parvenir avec Object.defineProperty
avec writable: false
en tant que paramètre.
var obj = {
"first": 1,
"second": 2,
"third": 3
};
Object.defineProperty(obj, "first", {
writable: false,
value: 99
});
Dans cet exemple, obj.first
a maintenant sa valeur verrouillée à 99.