JS Tip of the Day: Static Members Are Inherited

Static Members Are Inherited
Version: ES2015
Level: Intermediate

When using extends with class, you set up a relationship between two classes where one class inherits from another. This way, all instances of the subclass will inherit from the superclass.

class Parent {
    isParent () {
        return true;
    }
}

class Child extends Parent {
    isChild() {
        return true;
    }
}

let manChild = new Child();
console.log(manChild.isChild()); // true
console.log(manChild.isParent()); // true (inherited)

This inheritance also extends (see what I did there?) to the classes themselves, where the subclass will inherit static members of the parent class.

class Parent {
    static makesParents () {
        return true;
    }
}

class Child extends Parent {
    static makesChildren () {
        return true;
    }
}

console.log(Child.makesChildren()); // true
console.log(Child.makesParents()); // true (inherited)

When you don’t explicitly use extends, no statics are inherited, even though the class will implicitly inherit from Object.

class ImplicitObject {}
console.log(ImplicitObject.fromEntries([['prop', 'value']]));
// TypeError: ImplicitObject.fromEntries is not a function

But, if you want the static members of Object to be inherited, you can extend it explicitly.

class ExplicitObject extends Object {}
console.log(ExplicitObject.fromEntries([['prop', 'value']]));
// {prop: 'value'}

While static Object methods won’t recognize your subtype (ExplicitObject.fromEntries() won’t create ExplicitObject instances), statics from other types like Array do.

class SubArray extends Array {}
console.log(SubArray.from([]) instanceof SubArray); // true

When creating your own static methods, you may want to take this into consideration using this to refer to the current class rather than referring to it directly by name. Then subclasses inheriting that method will be using their own class rather than the original.

class Boat {
    static create () {
        return new this(); // this rather than Boat
    }
}

class Sub extends Boat {}

console.log(Boat.create() instanceof Boat); // true
console.log(Sub.create() instanceof Sub); // true

More info: