NodeJs: Use Object.freeze to block any modification to an object

I found this very interesting built-in javascript functionality that allows to freeze an object and it does not allow any modification.

Let’s take this very simple example.

class Foo
{
constructor() {
this.A = 1;
}
}
var foo = new Foo();
console.log(foo.A); // 1
foo.A = 10;
console.log(foo.A); // 10

Let’s apply the Object.freeze method.

If we apply the method and modify the object externally, the engine does not throw an error, but it still maintains the object as read only.

class Foo
{
constructor() {
this.A = 1;
Object.freeze(this);
}
}
var foo = new Foo();
console.log(foo.A); // 1
foo.A = 10;
console.log(foo.A); // 1

If we apply the method, but modify the object internally, then the engine does throw an error.

class Foo
{
constructor() {
this.A = 1;
Object.freeze(this);
this.A = 2;
}
}
var foo = new Foo();
// TypeError: Cannot assign to read only property 'A' of object '#<Foo>'

Personally, I dislike this inconsistency, but it still keeps the same result. TODO: verify why?

This also works with anonymous objects.

var foo = {
A: 1
};
Object.freeze(foo);
console.log(foo.A); // 1
foo.A = 10;
console.log(foo.A); // 1

If we use ES6 properties, then it works much better.

class Foo
{
constructor() {
this._A = 1;
Object.freeze(this);
}
get A() {
return this._A;
}
set A(value) {
this._A = value;
}
}
var foo = new Foo();

console.log(foo.A); // 1
foo.A = 10;
// TypeError: Cannot assign to read only property '_A' of object '#<Foo>'

What about arrays?

One caveat, this only works with top-level properties.

class Foo
{
constructor() {
this.A = 1;
this.B = [{
X: 2
}, {
X: 3
}];
this.C = [1,2,3];
Object.freeze(this);
}
}
var foo = new Foo();
console.log(foo.A); // 1
console.log(foo.B[0].X); // 2
foo.B[0].X = 20;
console.log(foo.B[0].X); // 20
foo.B.push({ X: 30 });
console.log(foo.B.length); // 3
foo.B.splice(2, 1);
console.log(foo.B.length); // 2

It does not block:

  • Modifying a property of an internal object in an array.
  • Adding or eliminating an item from an array.

If you want to block the addition or elimination of items of an array, you need to also freeze the array.

class Foo
{
constructor() {
this.A = 1;
this.B = [{
X: 2
}, {
X: 3
}];
this.C = [1,2,3];
Object.freeze(this);
Object.freeze(this.B);
}
}
var foo = new Foo();
console.log(foo.A); // 1
console.log(foo.B[0].X); // 2
foo.B[0].X = 20;
console.log(foo.B[0].X); // 20
foo.B.push({ X: 30 });
// TypeError: Cannot add property 2, object is not extensible

If you want to block a specific item, you need to block it explicitly. In this case, it follows what we saw in the beginning that no error was thrown, yet the field was kept as read only.

class Foo
{
constructor() {
this.A = 1;
this.B = [{
X: 2
}, {
X: 3
}];
this.C = [1,2,3];
Object.freeze(this);
Object.freeze(this.B);
Object.freeze(this.B[0]);
}
}
var foo = new Foo();
console.log(foo.A); // 1
console.log(foo.B[0].X); // 2
foo.B[0].X = 20;
console.log(foo.B[0].X); // 2

This was a very cool feature I found, and I hope this is useful for others.

Happy coding!

CTO of Juntoz.com, peruvian startup for ecommerce technology. Father, technology enthusiast, agilist, INTJ, Developer, Mini-Devops.