Inheritance with extends

The `extends` syntax creates a subclass relationship between JavaScript classes and links the relevant prototype chains. It lets instances inherit methods from the parent while allowing the child constructor to reuse or specialize parent behavior.

When a class `Child` extends `Parent`, instances of `Child` inherit instance methods through `Child.prototype`, whose prototype is `Parent.prototype`. This means a method defined on the parent can be found through normal property lookup on a child instance.

`extends` also connects the constructor functions themselves: `Child` inherits static properties and methods from `Parent` through the constructor's prototype chain. This is separate from the instance prototype chain, so interview answers should distinguish instance inheritance from static inheritance.

A derived constructor must call `super()` before it can use `this`. The `super()` call invokes the parent constructor and initializes the derived instance; a derived class can omit its constructor and receive an implicit constructor that forwards arguments to the parent.

A subclass can override inherited methods by defining a method with the same name. Inside an overridden method, `super.method()` can call the parent implementation, which is useful when the child wants to extend rather than completely replace the parent's behavior.

Key points

Interview questions

What does `extends` do in JavaScript?

`extends` declares one class as a subclass of another. Instances of the child can inherit instance methods from the parent's prototype. The child constructor also participates in a constructor inheritance chain, which is why static members can be inherited as well. If the child defines a constructor, it must call `super()` before using `this`.

Why must a derived constructor call `super()` before using `this`?

A derived class does not initialize its own `this` binding until the parent constructor has been invoked. Calling `super()` performs that parent initialization and makes `this` available to the derived constructor. Attempting to access `this` first throws a runtime error. If no constructor is declared in the derived class, JavaScript provides behavior that forwards the constructor arguments to the parent.

What is the difference between instance inheritance and static inheritance with `extends`?

Instance inheritance concerns objects created by the subclass: `Child.prototype` delegates to `Parent.prototype`, so child instances can find inherited methods. Static inheritance concerns the class constructor objects themselves: the child constructor inherits from the parent constructor. Consequently, a static method on the parent can be accessible through the child class, while an ordinary instance method is accessed through an instance.

How does `super.method()` work when a subclass overrides a method?

When a subclass method calls `super.method()`, it invokes the corresponding method from the parent class's prototype. The call is useful when the child needs the parent's behavior as part of a specialized implementation. The resulting method still operates with the current object as its receiver. This allows an override to extend parent behavior without duplicating the parent implementation.

What prototype relationships does `class Dog extends Animal` establish?

For instances, `Dog.prototype` has `Animal.prototype` as its prototype, so a `Dog` instance can reach inherited instance methods through that chain. Separately, the `Dog` constructor inherits from the `Animal` constructor, enabling static inheritance. This distinction explains why both `dog instanceof Animal` and `dog instanceof Dog` can be true. It also explains why inspecting only `Dog.prototype` does not show the complete inheritance behavior of the classes.