2

I wrote some classes that have private variables through the use of WeakMap(). I did this by placing a WeakMap at the top of the class file.

light.js

let privateVars = new WeakMap();

class Light {
  constructor(state, brightness) {
    let info = {"state": state, "brightness": brightness, "createdAt": Date.now()};
    // Save info into privateVars
    privateVars.set(this, info);
  }

  switch() {
    let info = privateVars.get(this);
    info.state = !info.state;
    privateVars.set(this, info);
  }
}

This worked fine, I was able to add some getters and setters, which had validation and type-checking.

Now I'm wanting to extend that class to another class but I'm having trouble sharing the private property information between the child and parent class files.

flashingLight.js

let privateVars = new WeakMap();
let flashing;

import Light from './light.js';

class FlashingLight extends Light {

  constructor(state=false, brightness=100, flashMode=true) {
    super(state, brightness);
    let info = {"state": state, "brightness": brightness, flashMode: flashMode, "createdAt": Date.now()};
    privateVars.set(this, info);
    if(flashMode===true) {
      this.startFlashing();
    }
  }

  startFlashing() {
    flashing = setInterval(this.lightSwitch,5000);
  }

}

When this.lightSwitch is called from the setInterval function inside startFlashing it can't access the state of the object.

Uncaught TypeError: Cannot read property 'state' of undefined
    at lightSwitch 

Is this because these functions are spread out across the two files? Is there anyway around this so that I can use both private variables and class extensions?

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
  • It is because you have two different variables named `privateVars`, and each file use it own version. – some May 19 '19 at 16:58
  • @some I updated with the error I get. Given I have 2 variables named `privateVars` and have set both, shouldn't I at least get back 1 of those 2 values? Instead it returns undefined. – Philip Kirkbride May 19 '19 at 17:15
  • In classical inheritance patterns, subclasses do not have access to base class private variables anyway. Are you intending to implement _protected_ variables? – Patrick Roberts May 19 '19 at 17:18
  • By the way, I see no implementation of `this.lightSwitch` anywhere. – Patrick Roberts May 19 '19 at 17:23
  • Ah, the second problem is with setInterval, where you pass a function, and `this` will not be what you want. You can use `setInterval(this.lightSwitch.bind(this),5000);` – some May 19 '19 at 17:24
  • @some thanks so much! Do you want to post as an answer or should I delete this? – Philip Kirkbride May 19 '19 at 17:26
  • 1
    @PatrickRoberts thanks for pointing that out. I should probably just pass `state` and `brightness` to `super()` and only worry about `flashMode` within my sub-class. If I need to use those variables in the sub-class I can use getter and setter methods. – Philip Kirkbride May 19 '19 at 17:27

1 Answers1

2

One of your problems is the usage of setInterval where you pass a function. When that function is called, this is not what you expected. You can use bind to force it to be what you want, like setInterval(this.lightSwitch.bind(this),5000)

some
  • 48,070
  • 14
  • 77
  • 93