Object.freeze() vs const vs let in JS

TLDR:

const applies to bindings (“variables”). It creates an immutable binding, i.e. you cannot assign a new value to the binding.

Object.freeze works on values, and more specifically, object values. It makes an object immutable, i.e. you cannot change its properties.


const creates an immutable binding

ES6 const does not indicate that a value is ‘constant’ or immutable. A const value can definitely change. The following is perfectly valid ES6 code that does not throw an exception:

const foo = {};
foo.bar = 42;
console.log(foo.bar);
// → 42

The only thing that’s immutable here is the binding. const assigns a value ({}) to a variable name (foo), and guarantees that no rebinding will happen. Using an assignment operator or a unary or postfix -- or ++ operator on a const variable throws a TypeError exception:

const foo = 27;
// Any of the following uncommented lines throws an exception.
// Assignment operators:
foo = 42;
foo *= 42;

ES6 const has nothing to do with immutability of values.

So, how to make a value immutable?

Primitive values, i.e. numbers, strings, booleans, symbols, null, or undefined, are always immutable.

var foo = 27;
foo.bar = 42;
console.log(foo.bar);
// → `undefined`

To make an object’s values immutable, use Object.freeze(). It has been around since ES5 and is widely available nowadays.

const foo = Object.freeze({
    'bar': 27
});
foo.bar = 42; // throws a TypeError exception in strict mode;
              // silently fails in sloppy mode
console.log(foo.bar);
// → 27

Note that Object.freeze() is shallow: object values within a frozen object (i.e. nested objects) can still be mutated. The MDN entry on Object.freeze() provides an example deepFreeze() implementation that can be used to make object values fully immutable.

Still, Object.freeze() only works on property-value pairs. There is currently no way to make other objects such as Dates, Maps, or Sets fully immutable.

const vs. let

The only difference between const and let is that const makes the contract that no rebinding will happen.

Everything I wrote here so far are facts. What follows is entirely subjective, but bear with me.

Given the above, const makes code easier to read: within its scope, a const variable always refers to the same object. With let there is no such guarantee. As a result, it makes sense to use let and const as follows in your ES6 code:

  • use const by default
  • only use let if rebinding is needed
  • (var shouldn’t be used in ES6)
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s