The extends keyword is used in class declarations or class expressions to create a class that is a child of another class. class ChildClass extends ParentClass { /* … */ }
The extends keyword can be used to subclass custom classes as well as built-in objects. Any constructor that can be called with new (which means it must have the
prototype property) can be the candidate for the parent class. function OldStyleClass() {
this.someProperty = 1;
}
OldStyleClass.prototype.someMethod = function () {};
class ChildClass extends OldStyleClass {}
class ModernClass {
someProperty = 1;
someMethod() {}
}
class AnotherChildClass extends ModernClass {}
The prototype of the ParentClass must be an Object or
null.Try it
Syntax
Description
function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3
Note: You would rarely worry about this in practice, because a non-object prototype doesn't behave as it should anyway. (It's ignored by the new operator.)
function ParentClass() {} ParentClass.prototype = 3; console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number!
extends will set the prototype for both ChildClass and ChildClass.prototype.
class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype;
The right-hand side of extends does not have to be an identifier. You can use any expression that evaluates to a constructor.
class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class
This is often useful to create mixins.
While the base class may return anything from its constructor, the derived class must return an object or undefined, or a TypeError will be thrown.
class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
If the parent class constructor returns an object, that object will be used as the this value for the derived class when further initializing class fields. This trick is called "return overriding", which allows a derived class's fields (including private ones) to be defined on unrelated objects.
Examples
Using extends
The first example creates a class called Square from a class called Polygon. This example is extracted from this live demo (source).
class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } }
Using extends with built-in objects
This example extends the built-in Date object. This example is extracted from this live demo (source).
class myDate extends Date { getFormattedDate() { const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; return `${this.getDate()}-${months[this.getMonth()]}-${this.getFullYear()}`; } }
Specifications
ECMAScript Language Specification # sec-class-definitions |
Browser compatibility
BCD tables only load in the browser