This question already has an answer here:
- Private properties in JavaScript ES6 classes 35 answers
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)
var speed = 10;
// public variable - still accessible outside Car
this.model = "Batmobile";
// public method
this.init = function(){
}
}
But in ES6, you can no longer declare vars outside the constructor, making it actually HARDER to work with classes in a OOP way!?
You can declare variables in the constructor using this, but that makes them public by default. This is very weird since ES6 DOES have a get / set keyword!
class Vehicle {
constructor(make, year) {
// the underscore is nice, but these are still public!
this._make = make;
this._year = year;
}
// get and set can be handy, but would make more sense
// if _make and _year were not accessible any other way!
get make() {
return this._make;
}
get year() {
return this._year;
}
}
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
and to use the module vehicle.js
client.js
However, symbols although unique, are not actually private since they are exposed via reflection features like Object.getOwnPropertySymbols...
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).
And you don't need to. You didn't do it in your ES5 constructor either. You can translate your code literally to
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.
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.
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.