3

When using a WeakMap Object in JavaScript, the get and set methods require a Key to be passed in as argument.

FYI, I'm using WeakMap to simulate private properties for a class, something like this:

window.MyObject = (function(){
  let _privateProperty = new WeakMap();
  class MyObject {
    constructor(value) {
      _privateVariable.set(this, value);
    }
    SamplePrivateGet() {
      return _privateVariable.get(this);
    }
  }
  return MyObject;
})();

My question is: is get and set performance influenced by the object used as key?

I know primitive types can't be used as key, but maybe using an object with only one property as key could be faster than using an object that has, say, one thousand properties.

I tried looking at ECMA specifications but it's not specified, my guess is it's because it would depends on the browser's implementation.

EDIT: There are two ways to approach this with WeakMaps, one is declaring a single _privateProperties WeakMap to which I will add my private properties, the other declare one WeakMap for each of the private properties. I'm currently using the second approach so that every WeakMap can be Garbage Collected separately, but maybe going with the first would allow me to make much less .get calls. But I guess that's out of the scope of the question :)

Fabio Lolli
  • 859
  • 7
  • 23
  • 1
    This kind of characteristic is not in the ECMAScript specification, it will depend on the engine implementation. I doubt the size of the object does affect the WeakMap performance at all, given the object *contents* aren't stored/copied into the map but just the reference. – Bergi Sep 20 '17 at 15:24
  • You don't need to use a WeakMap to simulate private vars. That's not what WeakMap is for. – Keith Sep 20 '17 at 15:24
  • @Keith He does not mean private variables, he means [private instance properties](https://stackoverflow.com/a/33533611/1048572) – Bergi Sep 20 '17 at 15:26
  • 1
    @Bergi Interesting!!, is this really any faster than a scoped var?. `A WeakMap can be used to avoid the previous approach's performance and memory penalty.` Really, what am I missing?, I'm sure he's right, but my logic seems to indicate not.!!. Also https://jsperf.com/truly-private-members for me the Symbol is the fastest, and WeakMap the slowest. – Keith Sep 20 '17 at 16:33
  • @Keith No, scoped variables are fastest. Their problem is that they require closure instantiation for every object. – Bergi Sep 20 '17 at 16:39
  • @Bergi Cheers, And I suppose it means you can still define class methods without `this.method` signature too.. That makes sense. – Keith Sep 20 '17 at 16:48
  • I was actually conflicted when I had to choose between WeakMap and Symbol to create private properties, I choose WeakMap because the idea behind that pattern made more sense to me in that situation, while Symbol seemed more of a hack. Anyway, another thing I should consider is: is it better to declare a single `_privateProperties` WeakMap holding an object to which I will add my private properties, or declare multiple WeakMaps, one for each private property I need? I'm currently going for the second one - that way each of the WeakMaps can be GCed separately, but I go through a lot more .get – Fabio Lolli Sep 21 '17 at 08:31

1 Answers1

-1

Not sure if this is good idea, but you could make kind of private instance properties by using Symbols.

const PRIVATE_VAR = Symbol('MY_CLASS::PRIVATE_VAR');
const PRIVATE_FUNC = Symbol('MY_CLASS::PRIVATE_FUNC');

export default class MyClass{ 
  constructor(value){
    this[PRIVATE_VAR] = value;
  }  
  [PRIVATE_FUNC](){ 
     /* ... */
  }
}

Without access to those Symbols values, it is quite hard to access those specific instance properties (plus instance properties defined with Symbols are non-enumerable in classes and objects).

btw 'Private instance methods and accessors' are at stage 3 so such solutions might not be relevant soon https://github.com/tc39/proposals

Nabuska
  • 443
  • 9
  • 17
  • 1
    Sure, [symbols are a viable approach to make semi-private properties](https://stackoverflow.com/q/22156326/1048572), but this doesn't answer the question. – Bergi Aug 19 '18 at 20:38