Schlaus Schlaus - 8 days ago 6
Javascript Question

Calling an overridden static method from parent

First, some code to set the stage:

var instances = [];

class Parent {
static doImportantStuff() {
console.log( 'Parent doing important stuff' );
return false;
}

static init() {
if ( this.doImportantStuff() )
instances.push( new this() );
}
}

class Child1 extends Parent {
static doImportantStuff() {
console.log( 'Child 1 doing important stuff' );
if (someCondition) return true;
return false;
}
}

class Child2 extends Parent {
static doImportantStuff() {
console.log( 'Child 2 doing important stuff' );
if (someOtherCondition) return true;
return false;
}
}


The idea is that there's a class
Parent
that several
Child
classes extend. Initialization of the
Child
classes is mostly the same, but each has their own implementation of
doImportantStuff()
, the return value of which indicated whether that particular
Child
should be instantiated.

So far this has worked in each transpiler I've tried, because
this
in the
Parent.init()
function refers to the constructor of the
Child
class. However I haven't found any documentation saying one way or the other about referring to a static method overridden by a child class, so the question is, can I rely on this always being so? Or, is there some other way to do this?

Answer

However I haven't found any documentation saying one way or the other about referring to a static method overridden by a child class, so the question is, can I rely on this always being so?

It's the standard function-call-via-object-property mechanism. When you do:

Child1.doImportantStuff();

...unless doImportantStuff is an arrow function (it isn't) or a bound function (it isn't), then during the call, this is set to Child1. Exactly like:

var obj = {
   foo: function() {
        console.log(this === obj);
   }
};
obj.foo();   // "true"

So yes, you can rely on that. (And I understand why you asked, it does seem a bit odd unless you work it through.)

Of course, it won't work from within the code of a non-static function, because this will refer to the instance, not the constructor function. If you needed it there, you could use this.constructor.doImportantStuff unless someone's messed up the constructor property. (People always used to mess it up; with the new syntax automating it, hopefully that will happen less although it's rare you really need it...)


For these kinds of questions, it's frequently useful to remember that the new class syntax is almost just syntactic sugar for the old verbose way we did it (if we were really thorough). It's really good sugar, but that's nearly all it is (and that's a Good Thing™). static methods are set as properties of the constructor function, non-static methods are set up as properties of the object on the constructor's prototype property. (I think the only non-sugar aspect of it is, as Bergi points out, that the new syntax lets us extend builtins like Array which it wasn't possible to do before. Part of making that possible relates to how and when this gets set up [you can't access it prior to the super() call in your subclass constructor], which relates to new.target, which Bergi discusses here. In ES7, it may go further beyond sugar with privacy stuff.)

Comments