123
123

Reputation: 23

Why do I need a WeakMap to store private data, as opposed to just closing over a variable with limited scope?

I'm trying to understand why I need to use WeakMaps to create private class members, instead of just using a normal variable. They both create encapsulation with closures, and module imports.

(function encapsulation() {
  const my_var = 'My secret info';
  const my_var2 = new WeakMap();

  class Test {
    constructor() {
      my_var2.set(this, 'My secret info 2');
      console.log(my_var); // My secret info
      console.log(my_var2.get(this)); // My secret info 2
    }
  }

  const t = new Test();
})();


console.log(my_var); // undefined
console.log(my_var2); // undefined

// Same result!

Upvotes: 2

Views: 353

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371019

The problem with an ordinary variable like my_var is that it will only save data for a single instantiation of the class:

const Test = (function encapsulation() {
  let my_var = 'My secret info';

  class Test {
    constructor(param) {
      my_var = param;
    }
    getInfo() {
      return my_var;
    }
  }
  return Test;
})();

const t1 = new Test('foo');
const t2 = new Test('bar');
console.log(t1.getInfo());
// the above returns 'bar'... uh oh, but we passed in 'foo' to `t1`! Our data is lost!
console.log(t2.getInfo()); // 'bar'

Thus, the need for a WeakMap, to hold separate data for each instantiation:

const Test = (function encapsulation() {
  const my_var2 = new WeakMap();

  class Test {
    constructor(param) {
      my_var2.set(this, param);
    }
    getInfo() {
      return my_var2.get(this);
    }
  }
  return Test;
})();

const t1 = new Test('foo');
const t2 = new Test('bar');
console.log(t1.getInfo()); // 'foo', as expected
console.log(t2.getInfo()); // 'bar', as expected

Upvotes: 4

Related Questions