Restrict modification of object properties in javascript.

Learn how to restrict adding, removing and changing or simply the modification of object properties in javascript.

Objects are the backbone of the javascript programming language as most of its features are actually object, like arrays, functions, etc.

So to make objects so powerful it was obvious that it should be able to modify or extend so that we can use it in different forms.

But there are scenarios where we want to restrict this modification to some limit or completely.

Here we will see two different objects methods that can you used to achieve the same.

Using Object.seal() to restrict object change.

First, we will see a scenario where we want to restrict an object to become extendible.

For example, we should be able to modify the existing properties or methods of the objects but cannot add a new one. Object.seal() can be used to achieve the same but it also marks all existing properties as non-configurable like we cannot delete them but just update their value if it is writable.

const obj = {
  prop: 42
};

Object.seal(obj);
obj.prop = 33;
console.log(obj.prop);
// 33

delete obj.prop; // cannot delete when sealed
console.log(obj.prop);
// 33

But we cannot restrict the modification of nested objects with Object.seal().

const obj = {
  prop: 42,
  nested: {
    a: 1,
    b: 2
  }
};

//Seal the object
Object.seal(obj);

obj.nested.a = 2;
delete obj.nested.a;
console.log(obj.nested.a);
// undefined

However, we can create another helper function which will deep seal or seal the nested objects as well.

function deepSeal(object) {
  // Retrieve the property names defined on object
  let propNames = Object.getOwnPropertyNames(object);

  // Seal properties before Sealing self
  for (let name of propNames) {
    let value = object[name];

    object[name] = value && typeof value === "object" ? 
      deepSeal(value) : value;
  }

  return Object.seal(object);
}

Now this will seal the nested objects as well.

const obj = {
  prop: 42,
  nested: {
    a: 1,
    b: 2
  }
};

//Seal the object
deepSeal(obj);

obj.nested.a = 2;
delete obj.nested.a;
console.log(obj.nested.a);
// 2

You can use Object.isSealed() to check if an object is sealed or not.

const obj = {
  prop: 42,
  nested: {
    a: 1,
    b: 2
  }
};

//Seal the object
deepSeal(obj);

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

Using Object.freeze() to restrict modification of object properties.

Unlike Object.seal(), Object.freeze() freezes the object completely. It does not even allow changing of object properties.

const obj = {
  prop: 42
};

Object.freeze(obj);

obj.prop = 33;
// Throws an error in strict mode

console.log(obj.prop);
// 42

But this also only shallow freezes the object properties.

const obj = {
  prop: 42,
  nested: {
    a: 1,
    b: 2
  }
};

Object.freeze(obj);

obj.nested.a = 33;
// Updates the value

console.log(obj.nested.a);
// 33

Like deepSeal() we can also create a deepFreeze() function that will freeze the nested objects as well.

function deepFreeze(object) {
  // Retrieve the property names defined on object
  var propNames = Object.getOwnPropertyNames(object);

  // Freeze properties before freezing self
  for (let name of propNames) {
    let value = object[name];

    object[name] = value && typeof value === "object" ? 
      deepFreeze(value) : value;
  }

  return Object.freeze(object);
}
const obj = {
  prop: 42,
  nested: {
    a: 1,
    b: 2
  }
};

deepFreeze(obj);

obj.nested.a = 33;
// Updates the value

console.log(obj.nested.a);
// 1

You can use Object.isFrozen() to check if an object is frozen or not.

const obj = {
  prop: 42,
  nested: {
    a: 1,
    b: 2
  }
};

//Seal the object
deepFreeze(obj);

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