Suggest an editImprove this articleRefine the answer for “The extends keyword”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`extends` puts one class into the prototype chain of another.** Writing `class B extends A {}` links `B.prototype` to `A.prototype` (this gives instance methods) and `B` itself to `A` (this gives static members), so the child gets both the methods and the statics of the parent. The child constructor calls the parent one through `super()`, and an overridden method reaches the parent implementation through `super.methodName()`. ```javascript class Dog extends Animal {} ``` **Key point:** `extends` creates two prototype links at once: `B.prototype.__proto__ = A.prototype` and `Object.setPrototypeOf(B, A)`.Shown above the full answer for quick recall.Answer (EN)Image**`extends` creates a child class and links it to the parent class through prototypes:** instances of the child receive the parent methods, and the child class itself receives the parent static members. Together with `super()` this is the complete inheritance mechanism of ES6 classes. ## Theory ### TL;DR - `class B extends A {}` performs two links: `B.prototype.__proto__ = A.prototype` and `Object.setPrototypeOf(B, A)`. - The first link gives inheritance of instance methods, the second gives inheritance of static methods and fields. - If the child declares its own `constructor`, it must call `super()` before the first access to `this`. - An overridden method can call the parent implementation through `super.methodName()`. - To the right of `extends` you may put any expression that returns a constructor: a class, a constructor function, or the result of a factory call. ### Quick example ```javascript class Animal { speak() { console.log("The animal makes a sound"); } } class Dog extends Animal { bark() { console.log("Woof-woof!"); } } const dog = new Dog(); dog.speak(); // "The animal makes a sound", the method is inherited dog.bark(); // "Woof-woof!" ``` `Dog` inherits every method of `Animal`, because lookup walks the chain `Dog.prototype`, then `Animal.prototype`, then `Object.prototype`. ### What extends does under the hood When you write: ```javascript class B extends A {} ``` the engine performs the equivalent of two operations: ```javascript B.prototype.__proto__ = A.prototype; // instance methods Object.setPrototypeOf(B, A); // static methods and fields ``` Two consequences follow: - instance methods (`B.prototype.method`) are looked up in `A.prototype` when they are missing from `B.prototype`; - static members (`A.staticMethod`) are reachable through `B` as well. So `extends` builds two different chains at once. For an instance: ```javascript // instance of B -> B.prototype -> A.prototype -> Object.prototype -> null ``` And a separate chain for the classes themselves, which are function objects: ```javascript // B -> A -> Function.prototype -> Object.prototype -> null ``` ### The child constructor and super() A child class can call the parent constructor through `super()`. ```javascript class Animal { constructor(name) { this.name = name; } } class Dog extends Animal { constructor(name, breed) { super(name); // calls the Animal constructor this.breed = breed; } } const dog = new Dog("Rex", "shepherd"); console.log(dog.name); // "Rex" console.log(dog.breed); // "shepherd" ``` Important: - if you declare your own `constructor` in the child, calling `super()` is mandatory before any use of `this`; - without it you get `ReferenceError: Must call super constructor before accessing 'this'`; - if there is no explicit constructor, the engine supplies `constructor(...args) { super(...args); }` itself. ### Overriding methods and super.methodName() A parent method can be overridden while still calling the old implementation through `super.methodName()`. ```javascript class Animal { speak() { console.log("The animal speaks"); } } class Dog extends Animal { speak() { super.speak(); // calls the parent implementation console.log("The dog barks"); } } new Dog().speak(); // The animal speaks // The dog barks ``` ### Inheriting static methods and fields If the parent has `static` members, they are inherited too: ```javascript class Animal { static category = "Animals"; static info() { console.log("This is the base class for animals"); } } class Dog extends Animal {} console.log(Dog.category); // "Animals" Dog.info(); // "This is the base class for animals" ``` This works precisely because of the second link: the lookup for `Dog.category` does not find it on `Dog` itself and climbs up to `Animal`. ### Inheriting from functions and dynamic expressions You can inherit not only from classes but also from plain constructor functions: ```javascript function Vehicle(name) { this.name = name; } Vehicle.prototype.drive = function () { console.log(`${this.name} is driving`); }; class Car extends Vehicle {} const car = new Car("BMW"); car.drive(); // "BMW is driving" ``` > `extends` works with any value that has a `prototype`, not necessarily with a `class`. The expression on the right is evaluated when the class is declared, so the base class can be chosen dynamically: ```javascript function getBaseClass(type) { return type === "cat" ? class Animal { speak() { console.log("Meow"); } } : class Animal { speak() { console.log("Woof"); } }; } class Pet extends getBaseClass("cat") {} new Pet().speak(); // "Meow" ``` This is a powerful technique: mixins, adapters and model factories all rest on it. **A summary of what `extends` gives you:** | What `extends` does | Description | | --- | --- | | Builds the prototype chain | `Child.prototype` inherits from `Parent.prototype` | | Lets you call the parent constructor | through `super()` | | Lets you call parent methods | through `super.methodName()` | | Inherits static methods and fields | `Child.staticMethod()` | | Works not only with classes | but with constructor functions too | | Accepts dynamic expressions | `class X extends getBaseClass()` | ### Common mistakes - Touching `this` in the child constructor before calling `super()`. That is always a `ReferenceError`, not `undefined`. - Believing that statics are not inherited. In fact `Dog.info()` works with no extra code. - Trying to inherit from an arrow function or from a plain object: they have no `prototype`, so you get a `TypeError`. - Calling the parent method as `Animal.prototype.speak.call(this)` instead of `super.speak()`. It works, but it breaks as soon as the hierarchy changes. - Confusing the two chains: `Dog.__proto__` is `Animal`, while `Dog.prototype.__proto__` is `Animal.prototype`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.