Protecting objects in JavaScript

This blog post is a quick refresher of how objects can be protected in JavaScript.
There are three levels of protection:

  1. Preventing extensions is the weakest level,

  2. sealing is stronger,

  3. freezing is strongest.





Preventing extension




Object.preventExtensions(obj)

makes it impossible to add properties to obj. Example:


var obj = { foo: 'a' };
Object.preventExtensions(obj);


Now adding a propert fails silently in sloppy mode:

> obj.bar = 'b';
> obj.bar
undefined


And throws an error in strict mode [1], which we switch to via an IIFE [2].

> (function () { 'use strict'; obj.bar = 'b' }());
TypeError: Can't add property bar, object is not extensible


You can still delete properties, though.

> delete obj.foo
true
> obj.foo
undefined


Checking whether an object is extensible




Object.isExtensible(obj)

checks whether obj is extensible:

> Object.isExtensible(obj)
false


Sealing




Object.seal(obj)

prevents extensions and makes all properties “unconfigurable”. The latter means that the attributes [3] of properties can’t be changed, any more. Read-only properties stay read-only, enumerable properties stay enumerable, etc.


(As an aside, JavaScript does allow you to change an unconfigurable property from writable to read-only, due to historical reasons.)


The following example demonstrates that sealing makes all properties unconfigurable.


> var obj = { foo: 'a' };

> Object.getOwnPropertyDescriptor(obj, 'foo') // before sealing
{ value: 'a',
writable: true,
enumerable: true,
configurable: true }

> Object.seal(obj)

> Object.getOwnPropertyDescriptor(obj, 'foo') // after sealing
{ value: 'a',
writable: true,
enumerable: true,
configurable: false }


You can still change the property foo:

> obj.foo = 'b';
'b'
> obj.foo
'b'


But you can’t change its attributes:

> Object.defineProperty(obj, 'foo', { enumerable: false });
TypeError: Cannot redefine property: foo


Additionally, obj is not extensible, any more.

Checking whether an object is sealed




Object.isSealed(obj)

checks whether obj is sealed:

> Object.isSealed(obj)
true



Freezing




Object.freeze(obj)

makes all properties non-writable and seals obj. That is, obj is not extensible, all properties are read-only and there is no way to change that.

var point = { x: 17, y: -5 };
Object.freeze(point);


Once again, you get silent failures in sloppy mode:

> point.x = 2; // no effect, point.x is read-only
> point.x
17

> point.z = 123; // no effect, point is not extensible
> point
{ x: 17, y: -5 }


And errors in strict mode:

> (function () { 'use strict'; point.x = 2 }());
TypeError: Cannot assign to read-only property 'x'

> (function () { 'use strict'; point.z = 123 }());
TypeError: Can't add property z, object is not extensible


Checking whether an object is frozen




Object.isFrozen(obj)

checks whether obj is frozen:

> Object.isFrozen(point)
true


References




  1. JavaScript’s strict mode: a summary

  2. JavaScript variable scoping and its pitfalls

  3. Object properties in JavaScript


Comments

Popular posts from this blog

Steve Lopez and the Importance of Newspapers

A Treasure Hunt Without The Treasure

Drop a ping-pong ball in the clown’s mouth