JavaScript - How to make objects immutable?
Tags: typescript, javascript, angular
Published: 2020-01-26 19:50:35

In this post, we will learn a couple of ways of creating immutable objects in JavaScript, as well what are the pros and cons of each approach. Object immutability will reduce side-effects and unpredictable behavior.
We will cover:
- const
- preventExtentions
- seal
- freeze

**Note**: this also applies for TypeScript

### 1. const

The first to come to mind is, of course, `const`, `const` **prevents re-assign the object** but the object's contents (e.g., its properties) can be altered.

Let's see the example:

```javascript
const person = {
	firstName: 'pera',
	lastName: 'trta',
	address: {
		street: 'street'
	}
}; 

// person = false;                    // re-assign is not allowed
person.firstName = 'pera pera';       // update is allowed
person.middleName = 'pt';             // add is allowed
person.address.street = 'street 123'; // update is allowed
delete person.lastName;               // delete is allowed
```

### 2. preventExtentions

As we saw, `const` has a drawback regarding object immutability. Another alternative is `Object.preventExtensions()` a method which **prevents adding new properties** to the object (updating and deleting existing properties is still allowed).

```javascript
const person = {
	firstName: 'pera',
	lastName: 'trta',
	address: {
		street: 'street'
	}
};

Object.preventExtensions(person);
// true
console.log(Object.isExtensible(person));

// person = false;                    // re-assign is not allowed
person.firstName = 'pera pera';       // update is allowed
person.middleName = 'pt';             // add is not allowed
delete person.lastName;               // delete is allowed
person.address.street = 'street 123'; // update is allowed *
person.address.newProperty = 7;       // update is allowed *
```
_* Please, keep reading, explanation is at the end of the post._

### 3. seal

Another Object's method is `seal`. This one will **prevent adding** (sealing an object prevents new properties from being added) **new and deleting existing properties** to and from the object (updating existing properties is still allowed).

```javascript
const person = {
	firstName: 'pera',
	lastName: 'trta',
	address: {
		street: 'street'
	}
};

Object.seal(person);

// sealed objects are by definition non-extensible
console.log(Object.isExtensible());
// true
console.log(Object.isSealed());

// person = false;                    // re-assign is not allowed
person.firstName = 'pera pera';       // update is allowed
person.middleName = 'pt';             // add is not allowed
delete person.lastName;               // delete is not allowed
person.address.street = 'street 123'; // update is allowed *
person.address.newProperty = 7;       // but here add is allowed *
```
_* Please, keep reading, explanation is at the end of the post._

### 4. freeze

Another Object's method is `freeze` - freezes an object. A frozen object can no longer be changed; freezing an object **prevents new properties from being added, updated or removed**.

```javascript
const person = {
	firstName: 'pera',
	lastName: 'trta',
	address: {
		street: 'street'
	}
};

Object.freeze(person);

// freezed objects are by definition non-extensible
console.log(Object.isExtensible());
// true
console.log(Object.isFrozen());

// person = false;                    // re-assign is not allowed
person.firstName = 'pera pera';       // update is not allowed
person.middleName = 'pt';             // add is not allowed
delete person.lastName;               // delete is not allowed
person.address.street = 'street 123'; // but here update is allowed *
person.address.newProperty = 7;       // here add is allowed as well *
```

### * So, what is going on lines with the asterisk sign? 

The result of calling `Object.preventExtensions(object)`, `Object.seal(object)`, `Object.freeze(object)` only applies to the immediate properties of object itself which means if the value of those properties are objects themselves (in our case property `address` is an object), those objects are not affected by the methods. The solution for this issue will be in another post.

Thank you for reading!