Start learning free

LESSON 182 OF 344 · OBJECT-ORIENTED PROGRAMMING

Inheritance in JavaScript: extends and super

Lesson Read the full explanation

TL ; DR:

A child class can inherit from a parent class — it gets all the parent's fields and methods for free, and can add its own. This lets you reuse code instead of copy-pasting it.


class Puppy extends Dog {
    whine() { console.log("whimper"); }
}


Full lesson:

Inheritance is one of the four classic OOP pillars (along with encapsulation, polymorphism, and abstraction). The idea is simple: most real-world things are kinds of other things — a Puppy is a Dog, a Car is a Vehicle, a Manager is an Employee. When you model that "is-a" relationship in code, the child class gets the parent's data and behavior automatically.

What gets inherited?

  • Fields — the Puppy has a name field even though we only declared it on Dog.
  • Methods — the Puppy can call bark() even though we only defined it on Dog.
  • The contract — anywhere code expects a Dog, you can pass a Puppy (we'll see this when we cover polymorphism).

What you still write

  • The constructor usually has to forward arguments up to the parent's constructor (because the parent's fields need initializing).
  • Any new methods or new fields specific to the child.

Your task

Below the Dog class, create a Puppy class that inherits from Dog and adds one new method, whine(), that prints "whimper". The harness creates a Puppy named "Buddy", calls its inherited bark(), and then its new whine().

Expected output:

Woof! I am Buddy
whimper
STEP 1 OF 2
    Ctrl + Enter to check

    JAVASCRIPT · OBJECT-ORIENTED PROGRAMMING

    Inheritance in JavaScript, explained

    The idea

    Many things are kinds of other things: a puppy is a dog, a car is a vehicle, a manager is an employee. Inheritance models that "is-a" relationship in code. A child class (also called a subclass) takes on the properties and methods of a parent class (the superclass) and can add its own. You write the shared code once, in the parent, instead of copying it into every class.

    The extends keyword

    You declare a child class with extends followed by the parent's name:

    class Puppy extends Dog {
        whine() {
            console.log("whimper");
        }
    }
    

    That is all it takes. A Puppy object can now do everything a Dog can do, plus whine().

    What gets inherited

    • Properties. A Puppy has a name, because the parent's constructor sets it.
    • Methods. A Puppy can call bark() although only Dog defines it.
    • The type. A Puppy counts as a Dog, so new Puppy("Buddy") instanceof Dog is true. Code written for dogs accepts puppies, which later lessons use for polymorphism.

    Inheritance goes one way. A plain Dog does not get whine(), and new Dog("Rex").whine() fails with TypeError because the method doesn't exist on it.

    Behind the scenes, JavaScript links the child's prototype to the parent's. When you call buddy.bark(), JavaScript looks for bark on buddy, then on Puppy, then on Dog, and runs the first one it finds. This chain of lookups is called the prototype chain.

    Constructors in subclasses

    If the child declares no constructor, JavaScript supplies one that passes all its arguments on to the parent's constructor. That is why new Puppy("Buddy") sets the name with no extra code.

    When the child needs a constructor of its own, for instance to add a new property, it must call super(...) to run the parent's constructor, and it must do so before touching this:

    class Puppy extends Dog {
        constructor(name, toy) {
            super(name);        // runs Dog's constructor
            this.toy = toy;
        }
    }
    

    Using this before super(), or never calling super() at all, throws ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor.

    Inside a child's method, super.bark() calls the parent's version of that method. That is useful when the child wants to add to the parent's behavior without replacing it, a topic the next lesson covers.

    The exercise, step by step

    The starter code defines Dog with a constructor and a bark method, then creates a Puppy named "Buddy" and calls bark() and whine() on it. Puppy doesn't exist yet.

    1. Declare the subclass. Below Dog, write class Puppy extends Dog { }. No constructor is needed, because the automatic one forwards "Buddy" to Dog, and bark is inherited.
    2. Add the new behavior. Inside Puppy, write a whine method that logs "whimper". Methods in a class body have no function keyword.

    The solution in JavaScript

    class Dog {
        constructor(name) { this.name = name; }
        bark() {
            console.log("Woof! I am " + this.name);
        }
    }
    
    class Puppy extends Dog {
        whine() {
            console.log("whimper");
        }
    }
    
    let buddy = new Puppy("Buddy");
    buddy.bark();
    buddy.whine();
    

    The output is:

    Woof! I am Buddy
    whimper
    

    The first line comes from Dog.bark, running on a Puppy object. The second comes from the method that only Puppy has.

    Common mistakes

    • Forgetting extends. A separate class Puppy { ... } has no link to Dog, so buddy.bark() fails with TypeError: buddy.bark is not a function, and the name is never set.
    • Copying the parent's code. Pasting bark into Puppy works, but a later fix to one copy leaves the other unchanged. Inherit instead.
    • Calling super too late or not at all in a constructor that you wrote yourself. Make super(...) the first statement.
    • Inheriting when the relationship isn't "is-a". A Dog has a Tail, but it isn't a tail, so a property is the better tool there. Prefer a short chain of classes over a deep one.
    • Extending more than one class. A JavaScript class can have only one parent.

    Key takeaways

    • class Child extends Parent gives the child all the parent's properties and methods.
    • A child without a constructor passes its arguments to the parent's; with one, it must call super(...) before using this.
    • A child can add new methods, and an object of the child class is also an instance of the parent.
    • Use inheritance for "is-a" relationships and keep hierarchies shallow.
    Keep going with JavaScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free