Private members in ES6

I’ve recently started to see a trend of methods prefixed with the underscore character in one of our projects at Sky. This is good in the sense that as our application is growing, and the number of methods we expose in our classes grows with it, the developers are considering what the public interfaces to these classes look like and finding a common pattern to distinguish the private interfaces.

However we’ve been able to hide away private methods and properties in JavaScript for a long time and prefixing those methods with an underscore, as some popular JS libraries and frameworks do ultimately ends in somebody using them where they shouldn’t.

With the new JavaScript class syntax we gain a slightly cleaner, more explicit in it’s intent syntax, we’ve actually been able to, and building private methods into Objects for some time now. I know many of the applications I wrote in ES5 used something along the lines of the “Immediately-Invoked Function Expression” or IIFE for short.

Working with ES6

This works very nicely as a pattern as the IIFE nicely encapsulates any of our methods that aren’t defined on the Service object. We could do the same thing using ES6, however if you’re already using ES6 then it’s likely you’re using Babel to transpile into ES5. We could accomplish the same above like so.

In this example we again will get a `privateMethod` is not a function if we try to call it, however I found that I needed to wrap my private method inside an object, otherwise Babel picked up during the transpilation process that the `this` within the `console.log function was undefined and changed this to undefined in the transpiled code.

Working with Symbols

A lesser known solution however is to use the new Symbol object.

A symbol is a unique and immutable data type and may be used as an identifier for object properties. The symbol object is an implicit object wrapper for the symbol primitive data type.

We can re-write the above code as follows using the Symbol object.

In the above code we define a symbol and assign it to a private constant. We can then both define the private method and call the private method using the square brackets syntax and passing in our Symbol as the name.

As symbols are unique, if we attempt to pass in a new symbol with the same string we will get an error as symbols are unique.

Wrapping up

My preferred solution for private members within JavaScript classes is to use Symbols. The syntax is less verbose and cleaner than in both previous examples as we don’t need to change the lexical scoping of this using the call method.

Unfortunately however there is still not support for Symbols within Internet Explorer, however if you’re already using a transpiler such as Babel then it’s likely you’re also using CoreJS polyfill.