Skip to content Skip to sidebar Skip to footer

How To Work With Private Variables In ES6?

In ES5, you could emulate a class with private and public variables like this: car.js function Car() { // using var causes speed to be only available inside Car (private) v

Solution 1:

ES6 standard does not offer a new way for defining private variables.

It's a fact, that new ES6 class is simply syntactic sugar around regular prototype-based constructors.

get and set keywords are offering a way for simplified definition of ES5 custom getters and setters that were previously defined with a descriptor of Object.defineProperty()

The best you could do is to use those techniques with Symbols or WeakMaps

The example below features the use of a WeakMap for storing private properties.

// myModule.js
const first_name = new WeakMap();

class myClass {
     constructor (firstName) {
          first_name.set(this, firstName);
     }

     get name() {
          return first_name.get(this);
     }
}

export default myClass;

I'm referring to article, written by David Vujic What? Wait. Really? Oh no! (a post about ES6 classes and privacy) with the idea of using WeakMaps.


Solution 2:

The same way than in ES5: define the methods that must access the private variables in the constructor instead of the prototype, thus making them privileged methods.

Otherwise there in no good way to allow prototypical methods to access private data, but still hide it from the outside. You can try symbols, weakmaps or handshakes, but IMO none is perfect. See accessing private member variables from prototype-defined functions for some ideas.


Solution 3:

But in ES6, you can no longer declare vars outside the constructor

And you don't need to. You didn't do it in your ES5 constructor either. You can translate your code literally to

class Car {
    constructor() {
        // local variable
        var speed = 10;

        // public property
        this.model = "Batmobile";

        // public method
        this.init = () => {
            …
        }; // using an arrow function here simplifies things
    }
}

Solution 4:

Update January 2016 - whilst I found the approach given in the accepted answer correct, I would like to state that using modules and symbols is an effective information hiding technique in ES2015+ (but Class attributes using Symbols will be hidden, not strictly private).

An effective, lightweight information hiding can be achieved through a combination of ES2015 modules (which would only export what you declare as exported) and ES2015 symbols. Symbol is a new built-in type. Every new Symbol value is unique. Hence can be used as a key on an object.

If the client calling code doesn't know the symbol used to access that key, they can't get hold of it since the symbol is not exported.

Quick example using your code:

vehicle.js

const s_make = Symbol();
const s_year = Symbol();

export class Vehicle {

  constructor(make, year) {
    this[s_make] = make;
    this[s_year] = year;
  }

  get make() {
    return this[s_make];
  }

  get year() {
    return this[s_year];
  }
}

and to use the module vehicle.js

client.js

import {Vehicle} from './vehicle';
const vehicle1 = new Vehicle('Ford', 2015);
console.log(vehicle1.make); //Ford
console.log(vehicle1.year); // 2015

However, symbols although unique, are not actually private since they are exposed via reflection features like Object.getOwnPropertySymbols...

const vals = Object.getOwnPropertySymbols(vehicle1);
vehicle1[vals[0]] = 'Volkswagon';
vehicle1[vals[1]] = 2013;
console.log(vehicle1.make); // Volkswagon
console.log(vehicle1.year); // 2013

Takeaway message - Modules in general are a great way to hide something because if not exported then not available for use outside the module, and used with privately stored Symbols to act as the keys, then class attributes too can become hidden (but not necessarily private). Class declarations are particularly well suited when considered as part of well constructed modules (amd, commonjs, or es6/2015).


Post a Comment for "How To Work With Private Variables In ES6?"