Let’s look at how we can make a JavaScript object property read-only using little-known built in functions.

JavaScript Object Literals are by dynamic by default. Given the following object:

1
2
3
4
var movieTicket = {
movie: "Mad Max",
hall: 1
};

It is possible to add, delete and modify properties after object creation:

1
2
3
movieTicket.price = '$10.00';
delete movieTicket.hall;
movieTicket.movie = 'The Rise And Rise Of Bitcoin';

The movieTicket will then look like:

1
2
3
4
{
movie: 'The Rise And Rise Of Bitcoin',
price: '$10.00'
}

Make a property read-only

You can make a property read-only by using the Object.defineProperty(obj, prop, descriptor) static function.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
var movieTicket = {
movie: 'Mad Max',
hall: 1
};
Object.defineProperty(movieTicket, 'movie', {
value: 'Mad Max',
writable: false
});
movieTicket.movie = 'Star Wars';
console.log(movieTicket);

will log Object {movie: "Mad Max", hall: 1}

Notes:

No error thrown when accessing a read-only property

After using the Object.defineProperty method on the movie property, the movie property can not be changed. But the system will not throw any error if you try to change its value. This can be an issue as, in a larger system, if you forget that a property is read-only, this might create nearly impossible to find bugs.

One workaround for this issue is to use 'use strict';. If you do and try to modify a read-only property, the code will thrown an error:

Uncaught TypeError: Cannot assign to read only property 'movie' of #<Object>

The property can still be deleted

If you make a property read-only using that method, you can still delete it using delete movieTicket.movie. If you re-add that property after that, the newly added property will not be read-only.

Sub properties are still modifiable

If your property points to an object, properties of that object are not read-only

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var movieTicket = {
movie: {
title: 'Mad Max',
year: 2015
},
hall: 1
};
Object.defineProperty(movieTicket, 'movie', {
value: {
title: 'Mad Max',
year: 2015
},
writable: false
});
movieTicket.movie.title = 'Sicario';
console.log(movieTicket.movie.title); // Returns: 'Sicario'

In that example, only the pointer to the movie child object is made read-only.