El mètode Object.freeze()
congela un objecte: és a dir, evita que se li puguin afegir noves propietats, eliminar propietats ja existents així com modificar els paràmetres d'enumerabilitat, configurabilitat i possibilitat d'escriptura de les propietats existents. Això, en essència fa que l'objecte esdevingui immutable a efectes pràctics. El mètode retorna l'objecte que s'ha congelat.
Sintaxi
Object.freeze(obj)
Paràmetres
obj
- L'objecte a congelar.
Descripció
Res pot ser afegit o eliminat del conjunt de propietats d'un objecte congelat. Qualsevol intent fallarà o bé sense reportar cap error o bé llençant una excepció TypeError
(és l'excepció més freqüent que serà llençada però en pot llençat altres tipus; a l'utilitzar el mode estricte).
Congelar un objecte també evita que es puguin modificar els valors de les seves propietats. Les propietats d'accés (getters i setters) segueixen funcionan (donant la il·lusió que s'ha canviat el valor). Cal advertir, però, que els valors que siguin objectes sí que es poden modificar, a no ser que aquests objectes també estiguin congelats.
Exemples
var obj = {
prop: function() {},
foo: 'bar'
};
// Es poden afegir noves propietats, així com canviar o eliminar les propietats ja existents
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
var o = Object.freeze(obj);
assert(Object.isFrozen(obj) === true);
// A partir d'ara qualsevol canvi fallarà
obj.foo = 'quux'; // falla silenciosament
obj.quaxxor = 'the friendly duck'; // romàn en silenci i no afegeix la propietat
// ...i en mode estricte qualsevol intent llençarà una excepció TypeError
function fail(){
'use strict';
obj.foo = 'sparky'; // llença TypeError
delete obj.quaxxor; // llença TypeError
obj.sparky = 'arf'; // llença TypeError
}
fail();
// Intentar realitzar canvis a través de Object.defineProperty també resultaran en excepcions
Object.defineProperty(obj, 'ohai', { value: 17 }); // llença TypeError
Object.defineProperty(obj, 'foo', { value: 'eit' }); // llença TypeError
L'exemple següent demostra que valors de tipus objecte pertanyents a propietats d'un objecte congelat sí que es poden modificar.(freeze
no s'aplica de manera recursiva).
obj1 = {
internal: {}
};
Object.freeze(obj1);
obj1.internal.a = 'aValue';
obj1.internal.a // 'aValue'
// Per a fer que obj sigui totalment immutable cal congelar tots els objectes referenciats per aquest.
// Per a aconseguir això utilitzem la funció següent
function deepFreeze(obj) {
// Obté els nomes de les propietats definides a l'objecte obj
var propNames = Object.getOwnPropertyNames(obj);
// Congela les propietats abans de congelar l'objecte en si
propNames.forEach(function(name) {
var prop = obj[name];
// Congela prop si aquest és un objecte
if (typeof prop == 'object' && !Object.isFrozen(prop))
deepFreeze(prop);
});
// Congela l'objecte pare
return Object.freeze(obj);
}
obj2 = {
internal: {}
};
deepFreeze(obj2);
obj2.internal.a = 'anotherValue';
obj2.internal.a; // undefined
Notes
A l'EcmaScript 5, si l'argument passat a aquest mètode no és un objecte (un valor primitiu), llençarà un TypeError
. A l'EcmaScript 6, un argument que no sigui un objecte serà tractat com si fós un objecte congelat ordinari, i simplement el retornarà.
> Object.freeze(1)
TypeError: 1 no és un objecte // Codi EcmaScript 5
> Object.freeze(1)
1 // Codi EcmaScript 6
Especificacions
Especificacions | Estat | Comentaris |
---|---|---|
ECMAScript 5.1 (ECMA-262) The definition of 'Object.freeze' in that specification. |
Standard | Definició inicial. Implementat a JavaScript 1.8.5. |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object.freeze' in that specification. |
Standard |
Compatibilitat amb navegadors
Característica | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Suport bàsic | 4.0 (2) | 6 | 9 | 12 | 5.1 |
Característica | Firefox Mobile (Gecko) | Android | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
Suport bàsic | ? | ? | ? | ? | ? |