Jannis Jannis - 3 months ago 24
Javascript Question

Accessing class data in static setter in ES6 classes

I am trying to achieve the following: Store data from subclasses in the superclass.

The following example does works in practice but I have been told that the use of

static get|set x() {}
in the example below is not correct since the
setter
method uses
this._data
which is out of the context of the immediate function, i.e. not passed into the function as an argument, and as such the setter is no longer static.

Example:

'use strict';

// base.js
class Base {
constructor () {}

static get data () {
return this._data;
}

static set data (newData) {
// merge newData into existing data
return this._data = _.assign({}, this._data, newData);
}
}

//------------------------------------------------------------------------------

// a.js
class A extends Base {
constructor () {
super();
}

add (obj) {
Base.data = obj;
}
}
let a = new A();
a.add({b: 'test'});
// -> Expectation: Base.data = { b: 'test' } now

//------------------------------------------------------------------------------

// b.js
class B extends Base {
constructor () {
super();
}

add (str) {
Base.data = {
someFixedKey: str
};
}
}
let b = new B();
b.add('hello');
// -> Expectation: Base.data = { b: 'test', someFixedKey: 'hello' } now


What I am trying to achieve here is to have a single superclass that sits at the base of multiple other subclasses and these subclasses can store their data in the superclass which then does PubSub notifications whenever the data changes and is able to send a full data object containing all data stored by all subclasses with that PubSub event.

If the setter/getter in my
base.js
are not
static
, the issue I was having is that
a.js
will only track
a.js
's data and not know about
b.js
's data.

If this is indeed an invalid use case of static getter/setter accessors, I may have to split out the data store ability into a separate singleton that tracks the data and is a dependency for all subclasses. Not the end of the world, but since this "works" I would like to learn more about the use case for static getters and setters.

Thanks for taking a look.




Update: Here is the example as a JS Fiddle which also demonstrates (in a reduced test case how it should work:



The question is: Regardless of whether a singleton/pubsub store would be better, is the use of
static
within the
Filters
superclass valid? Especially the
static set data (newData) {}
method since it actually accesses
this._data
and I have been told that for any method to be
static
I must not access anything outside that immediate function and since
this._data
is not passed into the method as an argument I should not use
static
here.

Answer

"Non working" example not using static

Yes, by not using static your properties will be set on each instance separately, so they aren't shared by anything.

I have been told that for any method to be static I must not access anything outside that immediate function and since this._data is not passed into the method as an argument I should not use static here.

Whoever told you that probably referred to instance properties. If you call a static method from an instance method, you cannot access the instance's properties using this of course, that's the whole point of static methods.
However, like in every other method call you can access properties of the object you are called upon, which for a static method is the class (constructor function) itself. Using this._data does access the static Base._data property - and that is what you want in your use case, so it's totally fine to use it.