JavaScript: Object Extensible and Prevent Modification

, , …,

In JavaScript, every object has a “attribute” (internal property) named “extensible”. It specifies whether properties can be added to the object. ECMAScript §8#sec-8.6.2

By default, all native objects (⁖ array, function, date, regex, …) and user-defined objects are extensible. Host objects (⁖ document) may or may not be extensible. 〔☛ What's Object in JavaScript?

You can set a object to be not extensible, but you cannot set a non-extensible object to be extensible.

Check If Object is Extensible (Can Add Properties?)

Object.isExtensible(obj) → return true if a object is extensible, else false. ECMAScript §15#sec-15.2.3.13

// check if a object is extensible (that is, whether properties can be added)

var uu = {}; // user-defined object
console.log(Object.isExtensible(uu)); // true

var aa = [3,4,5]; // Array
console.log(Object.isExtensible(aa)); // true

var dd = new Date(); // date object
console.log(Object.isExtensible(dd)); // true

Prevent Extension (Disallow Adding Properties)

Object.preventExtensions(obj) → make the object obj not extensible. ECMAScript §15#sec-15.2.3.10

// set the extensible attribute of a object to false

var u8 = {};

Object.preventExtensions(u8);

u8.pp = 3;                      // add a property

console.log(u8.pp);             // prints 「undefined」. add failed

console.log(Object.isExtensible(u8)); // false

Note: even if your object is not extensible, but its parents might, so people can add properties to the parent object, and your object may still get unexpected properties, due to inheritance.

Note: by spec, it is impossible to set a object's extensible attribute to true. ECMAScript §8#sec-8.6.2

Prevent Extension and Make ALL Properties Non-configurable

Object.seal(obj) will do 2 things:

ECMAScript §15#sec-15.2.3.8

(note: “configurable” is a attribute of property. When false, it means that property cannot be deleted (⁖ delete o.p) and this property's attributes {writable, enumerable, configurable} cannot be changed. 〔☛ JavaScript Property's Attributes: Writable, Enumerable, Configurable〕)

// seal a object.

var oo = {"p1":1, "p2":2};

console.log(Object.getOwnPropertyDescriptor(oo, "p1"));
// → { value: 1, writable: true, enumerable: true, configurable: true }

Object.seal(oo);

// configurable attribute for property p1 is now false
console.log(Object.getOwnPropertyDescriptor(oo, "p1"));
// → { value: 1, writable: true, enumerable: true, configurable: false }

// configurable attribute for property p2 is now false
console.log(Object.getOwnPropertyDescriptor(oo, "p2"));
// → { value: 2, writable: true, enumerable: true, configurable: false }

// Extensible attribute is now false
console.log(Object.isExtensible(oo)); // false

Check If Object is Sealed

Object.isSealed(o)true if object o is sealed, else false. ECMAScript §15#sec-15.2.3.11

var oo = {"p1":1, "p2":2};
console.log(Object.isSealed(oo)); // false
Object.seal(oo);
console.log(Object.isSealed(oo)); // true

「Object.freeze()」 = 「Object.seal()」 + Make ALL Properties Non-writable

Object.freeze(obj) will do 3 things:

ECMAScript §15#sec-15.2.3.9

(Note: when a property's “writable” attribute is false, you cannot change the property's value. 〔☛ JavaScript Property's Attributes: Writable, Enumerable, Configurable〕)

// freeze a object.

var oo = {"p1":1, "p2":2};

console.log(Object.getOwnPropertyDescriptor(oo, "p1"));
// → { value: 1, writable: true, enumerable: true, configurable: true }

Object.freeze(oo);

console.log(Object.getOwnPropertyDescriptor(oo, "p1"));
// → { value: 1, writable: false, enumerable: true, configurable: false }

console.log(Object.getOwnPropertyDescriptor(oo, "p2"));
// → { value: 2, writable: false, enumerable: true, configurable: false }

// Extensible attribute is now false
console.log(Object.isExtensible(oo)); // false

Check If Object is Frozen

Object.isFrozen(o) → return true if object o is frozen. ECMAScript §15#sec-15.2.3.12

var oo = {"p1":1, "p2":2};
console.log(Object.isFrozen(oo)); // false
Object.freeze(oo);
console.log(Object.isFrozen(oo)); // true
blog comments powered by Disqus