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

Ideas for fixing unconnected computing

Omar to kill me