There is a lot of talk nowadays related to the benefits of immutability in programming languages. Functional languages such as F# and Scala are gaining more popularity because of this. Commonly considered object oriented languages such as C# and Java go more functional with each release, Java including lambdas in version 8 (although that is not directly related to immutability) and C# having the immutable collections and new features in version 6 such as get only auto-properties, initializers for automatically implemented properties and primary constructors, which can be combined together to write immutable classes/structures with less code.
Usually in those cases, the most highlighted benefit of immutability is that since you don’t have to worry about mutable state you can write lock free multithreaded code, a thing that is becoming more important as the processing power of one CPU core is not going to continue growing in the future (unless until Quantum computers arrive, but I have no idea of how that would work). That benefit comes from the guarantees that computers can make about immutable state.
Immutability in ECMAScript 5
ECMAScript 5 introduced the ability to make objects immutable through the use of Object.freeze(obj)
. As the documentation explains, the method:
- Prevents the addition of new properties to the object.
- Prevents the removal of existing properties
- Prevents changes on any of the characteristics of existing properties.
“In essence the object is made effectively immutable.”
Considering the current state of JavaScript writing multithreaded is not one of the goals for which this feature was designed. Nevertheless, considering JavaScript’s dynamic nature I think it was done because:
- It should be potentially possible for engines to optimize code based on the knowledge that an object is immutable (although it seems that is not the case right now).
- Sometimes it’s easier to reason about things if you are sure they won’t change.
APIs for working with immutable elements
Considering all of the above, a fairly common scenario would be to want to create a new object similar to an existing one but changing some values from the original object. F# provides the following syntax for records through the usage of with
:
A similar API in C# would look like this (and some pains about it are documented in this post):
To achieve the same thing in JavaScript we could create methods for each field, similar to the C# example. That could be either manual or automatic, the latter by calling a function passing the object as a parameter and creating a function for each field.
And then there’s another option…
Using Proxy to implement the API
The first thing we need to do is agree on how the API will be consumed. My proposal is:
Now let’s set some requirements:
- When calling
immutable(obj)
the objectobj
becomes immutable. - The
with...
methods only perform a shallow copy. They should maintain the prototype chain. - Only fields can be set using
with...
, methods can’t.
Before we get into the implementation details it’s important to remark that the Proxy feature is part of the unfinished ECMAScript 6 specification. The documentation is really good so I won’t delve into the details of how the feature works.
A potential implementation could look like this:
Testing things out
At the time of writing the only browser that supports the latest version of the specification is Firefox. I’m using version 29.0.1 and running this gist.
The output is: