Published: 2018-01-19
Updated: 2018-01-20
Web: http://fritzthecat-blog.blogspot.com/2018/01/es6-private-class-fields-workarounds.html
ES6
classes provide no privacy in the sense of
access modifiers.
In other words, encapsulation lacks.
The ES6 tutorial
proposes four ways to achieve privacy, from which one is not real,
because it is just the convention to use _underscore
as prefix for private variables.
Which would not prevent corruption in any way.
The other three ways, in my opinion, are actually not usable in real world. This Blog presents them in examples, and tries to show up their costs, so that you can decide this on your own.
Click onto one of the left-side buttons to see an example script and its description.
Below you find an output area for console.log()
messages.
You can also edit the script and execute it again by using the "Execute Script" button.
ES6 encapsulation is strongly connected to
modules,
there you can have invisible functions outside of an exported class.
The restriction is that these must receive all their information via parameters,
because they are not connected to any object-instance, they are like Java static
.
This is definitely the best, safest and most general solution if you absolutely want ES6 privacy for any price.
The class CountDown
defines a private variable counter
in its constructor.
This variable exists just in the block-scope of the constructor,
but it survives the constructor execution due to functions
increment()
, decrement()
and getValue()
referencing it.
But it is not accessible by any class-method outside the constructor!
Mind that this counter can not be a class-property, because it would be public then by default.
The ugly thing about this solution is that all class-methods that deal with private fields
have to be implemented inside the constructor body,
and all private fields also have to be there.
Thus we lose the elegant ES6 syntax for class methods.
Because most public methods will want to call private ones, or use private fields,
everything, the whole class body, has to go inside the constructor!
The nice thing about this solution is that you can also define private functions inside the constructor body.
Just don't put them onto the this
pointer, do it like reset()
.
This is a solution that works just when your class is encapsulated in an ES6 module.
For each private field of the class you need one WeakMap
.
The constructor, or any setter, stores the value of a field into the according map, using this
as key.
Any getter would read it from the map the same way.
We could regard this as an hidden internal instance management,
to be stereotyped in every class that needs privacy.
Extremly ugly is the necessity to have one map for each field.
Further you can not have private methods with this solution.
Why is the instance-management done with WeakMap
?
When the class instance, which is the map-key, wouldn't be referenced any more,
it and all its field values would disappear by garbage-collection.
A normal Map
ould never release the object!
ɔ⃝ Fritz Ritzberger, 2018-01-19