Explain the concept of inheritance in ES2015 classes
TL;DR
JavaScript class inheritance uses extends to link constructor and prototype chains. A derived constructor must call super() before accessing this, and super.method() invokes parent behavior. Use inheritance when the child is genuinely substitutable for the parent and the contract is stable. Prefer composition for optional capabilities or when subclasses would need to override many unrelated methods.
class Animal {constructor(name) {this.name = name;}speak() {console.log(`${this.name} makes a noise.`);}}class Dog extends Animal {constructor(name, breed) {super(name);this.breed = breed;}speak() {console.log(`${this.name} barks.`);}}const dog = new Dog('Rex', 'German Shepherd');dog.speak(); // Rex barks.
The two chains created by extends
ES2015 class inheritance links both instance methods and static members through separate prototype relationships.
Instance method lookup uses the lower prototype chain, while inherited static methods use the constructor chain.
Inheritance in ES2015 classes
Basic concept
Inheritance in ES2015 classes allows a class (child class) to inherit properties and methods from another class (parent class). This promotes code reuse and a hierarchical class structure.
Using the extends keyword
The extends keyword is used to create a class that is a child of another class. The child class inherits all the properties and methods of the parent class.
class ParentClass {constructor() {this.parentProperty = 'I am a parent property';}parentMethod() {console.log('This is a parent method');}}class ChildClass extends ParentClass {constructor() {super(); // Calls the parent class constructorthis.childProperty = 'I am a child property';}childMethod() {console.log('This is a child method');}}const child = new ChildClass();console.log(child.parentProperty); // I am a parent propertychild.parentMethod(); // This is a parent method
Using the super keyword
The super keyword is used to call the constructor of the parent class and to access its methods. This is necessary when you want to initialize the parent class properties in the child class.
class Animal {constructor(name) {this.name = name;}speak() {console.log(`${this.name} makes a noise.`);}}class Dog extends Animal {constructor(name, breed) {super(name); // Calls the parent class constructorthis.breed = breed;}speak() {super.speak(); // Calls the parent class methodconsole.log(`${this.name} barks.`);}}const dog = new Dog('Rex', 'German Shepherd');dog.speak();// Rex makes a noise.// Rex barks.
Method overriding
Child classes can override methods from the parent class. This allows the child class to provide a specific implementation of a method that is already defined in the parent class.
class Animal {speak() {console.log('Animal makes a noise.');}}class Dog extends Animal {speak() {console.log('Dog barks.');}}const dog = new Dog();dog.speak(); // Dog barks.