Fragmented Thought

JavaScript class static constants extension on instances

Ran into an interesting question from a coworker. We were working through surprising (to me) PHP behavior on the usage of self:: vs static::. It's a question of late binding and the accessor. For a PHP reference to get a class's extended constant value from the subclass, you had to use static::.

Then they asked me how it works in JavaScript as we're moving toward React (woo). Had to admit, I had no idea. While I do use JS classes, it's more composition than inheritance if possible. Still, it's useful to know. There's an example below, but the take away is this:

Static constants are somewhat second class, and shouldn’t be used for extension based overrides. Preference functions in javascript.

class ClassA {
    public static MY_VALUE = 'asdf';

    // Possible, but one hell of an awkward turtle.
    // getOutput(){
    //     // @ts-ignore // Required to allow for __proto__ access
    //     return this.__proto__.constructor.MY_VALUE;
    // }

    getOutput(){
        return ClassA.MY_VALUE;
    }
}

class ClassB extends ClassA {
    // Note that WebStorm doesn't even find this be an extended / overridden property
    public static MY_VALUE = 'fdsa';

    // This shows extension.
    getOutput(){
        return ClassB.MY_VALUE;
    }
}

const a = new ClassA();
const b = new ClassB();

describe('constants usage', () => {
    it('a instance of ClassA', () => {
        expect(a).toBeInstanceOf(ClassA)
    });

    it('b instance of ClassB', () => {
        expect(b).toBeInstanceOf(ClassB)
    });

    it('a should return ClassA value of MY_Value', () => {
        expect(a.getOutput()).toBe(ClassA.MY_VALUE)
    });

    it('b should return ClassB value of MY_Value', () => {
        expect(b.getOutput()).toBe(ClassB.MY_VALUE)
    });

});