Private properties
In ES6 (and before), all private property implementations rely on closure .
People did this even before JavaScript had versions. WeakMap is simply a variation that eliminates the need for a new area and new functions for each new object due to access speed.
A symbol is an ES6 variant that hides an attribute from general operations, such as simple access to properties or for in .
As you can see above, it can be bypassed by Object.getOwnPropertySymbols () . Despite its existence, I always select a symbol over WeakMap. The code is cleaner, simpler, gc works less, and (I think) is more efficient.
I personally avoid the class . Object.create much simpler. But that goes beyond that.
Protected Properties
Protected properties, by their nature, require the executing function to know the object of the calling code in order to determine if it should be provided.
This is not possible in JS, and not because ES6 does not have a real class , but because the context of the caller is simply inaccessible .
Due to various special JavaScript natures , it remains impossible for foreseeable future protected properties.
On the other hand...
Package Properties
Some languages have semi-secure properties, sometimes called "private private", where the method / property is available to members in the same module / package.
ES6 can implement it with closure. This is exactly the same as the private property code above - just share the area and its symbols with several prototypes.
But this is impractical, since this requires that the entire module be defined in the same closed area, that is, in one file. But this is an option nonetheless.