Douglas Crockford says that privacy/privileged methods are possible via
closures (2001). Things have changed a little since then, but that’s a good start.
4 different ways to accomplish information hiding
Rauschmeyer mentions 4 different ways to accomplish privacy:
- Keeping data private in the class constructor
- Underscore prefix naming conventions for private member variables
- WeakMaps and WeakSets
- Using Symbols as keys for private properties
Let’s discuss these 4 techniques.
Option 1. Keeping data private in the class constructor
Methods in the constructor are private. These are called
instance methods. This is very normal for most languages.
Instance methods take up extra memory.
Prototype methods are “shared”.
The constructor method is usually agreed on as one of the better methods. Use let or const to keep it block scoped. The important part is that the arguments go into the constructor, not the class (similar to C++ copy constructors) in the JS constructor, and we keep things in the constructor to guarantee privacy and encapsulation.
This article assumes a basic familiarity with C++ programming, the Rule of Three, and OOP. We won’t cover it here.
Option 2. Underscore prefix naming convention for private member variables
This has the drawback of not actually being private.
Option 3. WeakMaps and WeakSets
Actual Use Cases for WeakMaps:
- Actual Uses of WeakMaps, Stack Overflow
- WeakMaps are used commonly in JS for information hiding.
- They were (are?) used in Firefox Developer Tools.
- They are used in credentials. (I’ve seen it).
The use cases for these structures were not intuitively obvious to me at first.
It’s a little bit more intuitive when you recall how weak pointers pointers work.
Recall that smart pointers are used in modern C++ to allocate temporary ownership.
Weak pointers are a subset of that. If you’re confused by this, read first about
smart pointers, then about
WeakMaps/Set concepts and concerns are somewhat similar to the concepts of weak pointers and shared memory and shared state concepts and concerns. These structures are created to avoid memory leaks for collections - and also, they are commonly used for information hiding/encapsulation.
- Weakly held references (think about how weak/smart pointers work)
- NOT enumerable!! If they were, you could see their data. (There are, of course, getters).
- WeakMaps: keys must be Objects.
- WeakSets: data types must be Objects.
On Garbage Collection And WeakMaps / WeakSets
Garbage collection uses nondeterminism to intelligently clean up memory.
With regular maps and sets, there is “no” garbage collection for recently deleted items. The deleted items are GC’ed after the collection itself is deleted. There is no element-by-element GC management.
For the lifetime of the Map, references to its keys and values are held indefinitely. This blocks garbage collection for keys and values of that Map.
Access happens via iteration/enumeration of keys via indexes.
WeakMaps allow deleted elements to be garbage collected; the collection itself does not indefinitely hold references to its keys. Garbage collection is nondeterministic. That means that the order of and access to the WeakMap collection is nondeterministic if based on enumeration/iteration.
Hence, WeakMaps aren’t enumerable.
This makes them more secure, because accessors must have a specific reference to that items. WeakMaps can be used in credentials, for example, or
This also makes them better at handling state changes, Promise handling, and much more.
This Stack Overflow post covers a lot of what I’ve been told by senior engineers, which also aligns with my research.
Option 4. Using Symbols as keys for private properties
The (somewhat obscure) case for using Symbols for privacy/information hiding has been made on occasion, but as Rauschmeyer posits,
it’s not the safest method because properties and Symbols are still enumerable using
Use common sense (i.e. constructors) most of the time for encapsulation of private member variables and data in JS.
When required, use WeakMaps and WeakSets.
See you next time, Amanda