How does JavaScript emulate private members? Back

As we all know, the proposal of private instance fields in classes has been pushed towards stage 4 since ES2022. It means that we can define private members inside classes like other OOP languages, which are limited to access outside a class in user code.

How does JavaScript emulate such behaviour? Use WeakMap. For why? The MDN document has given us the answer:

  • Compared to a Map, a WeakMap does not hold strong references to the object used as the key, so the metadata shares the same lifetime as the object itself, avoiding memory leaks.
  • Compared to using non-enumerable and/or Symbol properties, a WeakMap is external to the object and there is no way for user code to retrieve the metadata through reflective methods like Object.getOwnPropertySymbols.

      class A {
          constructor() {
              this[Symbol('#private')] = 'unreachable value?';
          }
      }
    
      // we can access it actually:
      const a = new A();
      a[Object.getOwnPropertySymbols(a)[0]]; // => "unreachable value?"
    
  • Compared to a closure, the same WeakMap can be reused for all instances created from a constructor, making it more memory-efficient, and allowing different instances of the same class to read the private members of each other.

The detailed implementation when the runtime environment does not support the proposal:

const A = (function () {
    // use a closure to ensure that the weak map cannot be accessed outside the class A
    const privates = new WeakMap();
    return class {
        constructor() {
            privates.set(this, {['#private'] : 'unreachable value?'});
        }
        getPrivateValue() {
            return privates.get(this)['#private'];
        }
    }
})();

const a = new A();
// the private member can only be accessed via an exposed method
a.getPrivateValue(); // => "unreachable value?"
Empty Comments
Sign in GitHub

As the plugin is integrated with a code management system like GitLab or GitHub, you may have to auth with your account before leaving comments around this article.

Notice: This plugin has used Cookie to store your token with an expiration.