ES6 `const` not immutable

There's a curious case in the ES6 specification of JavaScript where variables declared with const are mutable. If a variable is declared as a primitive like the following, const foo = 123, it is immutable but if a variable is declared as an object(const bar = {}) it is mutable. This happens because the new variable always points to the same object but the properties on that object can change. So, the following code is perfectly acceptable in ES6 and will probably not behave as you expect:

(() => {
  const my_object = {
    foo: 'bar'
  };

  my_object.baz = 'totally mutable';
  my_object.foo = 'why no breakage?';

  console.log(my_object);
})()

On the other hand, the following code will throw a syntax error as expected:

(() => {
  const primitive = 1234;

  primitive = 5678; // Throws an error!
})()

This happens because the variable is just a reference to an object. That object's properties are not part of the reference so while const my_object refers to Object#1234 it actually has no bearing on what that objects properties are, only where the object itself lives. Interestingly, we can use the Object#freeze method to prevent this behavior and constantize the properties of that object. However, if one of those properties is also an object, it will supper the same problem. In order to have a fully constant object in ES6, you'll need to use the following function to make the entire object constant:

(() => {
  const my_object = {
    foo: {
      bar: {}
    }
  };

  var constantize = (obj) => {
    // constantizes the first level of properties of the object.
    Object.freeze(obj);
    // iterates over the properties of the object and constantizes them recursively.
    Object.keys(obj).forEach( (key, value) => {
      if ( typeof obj[key] === 'object' ) {
        constantize( obj[key] );
      }
    });
  };

  constantize( my_object );
})();

That should iterate over all the object-properties in any given root object and make them all constants.

I hope this helps somebody who's run into a scoping or mutability problem! Check out the MDN documentation on const, their docs on Object#freeze or the draft of the ES6 spec for more explicit details.

Update: @fizk pointed out on twitter that "constant" and "immutable" are not the same thing. As seen in this stackexchange post they're very different concepts. While "immutable" works more like I described above creating(depending on the language) an object whose properties cannot be changed, "constant"(again depending on the language) is like a toned-down version of "immutable" providing limited safety within a certain context or as in the case with javascript only providing the safety that a variable will reference a particular object in memory.