Fragmented Thought

JavaScript class static constants extension on instances

By

Published:

Lance Gliser

Heads up! This content is more than six months old. Take some time to verify everything still works as expected.

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) }); });