For more tips like this, sign up to the weekly newsletter!

Use Object.freeze for easy immutability

Using immutable structures is one way for more defensive coding. This way you can be sure that no one else can modify your objects.

A good example is when you have a central place to set application-wide data, and you want to control how it is modified. (it's no coincidence that Redux heavily promotes immutability)

Basics

The simplest way is to use Object.freeze(obj) which makes the parameter object immutable.

const obj = {prop: "property"};
const frozen = Object.freeze(obj);

Objects that are frozen can not be modified.

frozen.prop = "new";
console.log(frozen.prop); // property

The can not part is more tricky. In older execution environments, it silently fails, like in the example above. But it may throw an exception instead, for example in strict mode:

(() => {
  "use strict";
  try{
    frozen.prop = "new";
  }catch(e) {
    console.log("Error"); // Error
  }
})();

Use Object.isFrozen(obj) to check whether a given object has been frozen.

console.log(Object.isFrozen(frozen)); // true

Caveats

Confusingly, Object.freeze freezes the argument object and not just the result.

console.log(Object.isFrozen(obj)); // true

This is a side effect. Depending on the code, it might be better to copy the object before freezing. Use Object.assign({}, obj) to achieve this.

const obj = {prop: "property"};
const frozen = Object.freeze(Object.assign({}, obj));

console.log(Object.isFrozen(frozen)); // true
console.log(Object.isFrozen(obj)); // false

Finally, Object.freeze does not make the entire object tree immutable, think of it as a shallow freeze. If an object contains another object, the inner one is still mutable.

const obj = {
  inner: {
    prop: "property"
  }
};
const frozen = Object.freeze(obj);
frozen.inner.prop = "new";
console.log(frozen.inner.prop);	// new

Final remarks

Since frozen objects are drop-in replacements to normal objects, Object.freeze is a great way of adding immutability to your project without adapting to a new API (which is the case for most libraries, for example, ImmutableJS)

Try it
References
Learn more: