Make JavaScript Objects Immutable with Object.freeze()
There's some confusion about how to make an object immutable in JavaScript. The ES6 const
keyword prevents you from overwriting an object, but it does not prevent you from changing an object's properties.
const obj = { answer: 42 };
// Even though `obj` is declared with `const`, you can modify
// any properties of `obj`.
obj.answer = 43;
++obj.answer;
obj.otherProperty = 'test';
Object.assign(obj, { anotherProperty: 'test2' });
// You **cannot** overwrite `obj` by assigning to it. This code
// throws an error "assignment to constant variable"
obj = { answer: 41 };
Freezing an Object
The Object.freeze()
function "freezes" an object. JavaScript prevents you from adding, removing, or modifying the properties of a frozen object.
const obj = Object.freeze({ answer: 42 });
// Since `obj` is frozen, modifying any of its existing
// properties or adding a new property throws an error:
// "Cannot assign to read only property 'answer' of object '#<Object>'"
obj.answer = 43;
However, Object.freeze()
is not recursive. You can still modify
nested object properties.
const obj = Object.freeze({ nested: { answer: 42 } });
// Does **not** throw an error. `obj` is a frozen object,
// but `nested` is not.
obj.nested.answer = 43;
There are numerous utilities for recursively freezing objects, including deep-freeze.
Strict Mode
Be very careful relying on Object.freeze()
: Object.freeze()
does not throw an error outside of strict mode. Even if you freeze()
an object in a function that uses strict mode, modifying that object
outside of strict mode won't throw an error.
function strict() {
'use strict';
return Object.freeze({ answer: 42 });
}
function run() {
const obj = strict();
// No error because this function is not in strict mode
++obj.answer;
obj.answer; // Still 42
}
run();