Inheritance with extends
Inheritance lets one class reuse behavior from another class.
The parent class is called the superclass or base class.
The child class is called the subclass or derived class.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
bark() {
return `${this.name} barks`;
}
}
const dog = new Dog("Bruno");
console.log(dog.speak()); // Bruno makes a sound
console.log(dog.bark()); // Bruno barksDog inherits from Animal.
The extends Keyword
Use extends to create a child class.
class Child extends Parent {}Example:
class User {
constructor(name) {
this.name = name;
}
describe() {
return `User: ${this.name}`;
}
}
class Admin extends User {
deleteUser() {
return "User deleted";
}
}An Admin instance can use methods from both Admin and User.
const admin = new Admin("Alice");
console.log(admin.describe()); // User: Alice
console.log(admin.deleteUser()); // User deletedsuper() in Constructors
If a child class has its own constructor, it must call super() before using this.
class User {
constructor(name) {
this.name = name;
}
}
class Admin extends User {
constructor(name, permissions) {
super(name);
this.permissions = permissions;
}
}
const admin = new Admin("Alice", ["delete-users"]);super(name) calls the parent constructor.
It sets up the parent part of the instance.
Why super() Must Come First
This is invalid:
class Admin extends User {
constructor(name, permissions) {
this.permissions = permissions; // ReferenceError
super(name);
}
}In a derived class constructor, JavaScript does not allow this before super().
Correct:
class Admin extends User {
constructor(name, permissions) {
super(name);
this.permissions = permissions;
}
}Method Overriding
A child class can define a method with the same name as a parent method.
class Animal {
speak() {
return "Animal sound";
}
}
class Dog extends Animal {
speak() {
return "Woof";
}
}
const dog = new Dog();
console.log(dog.speak()); // WoofThe child method overrides the parent method.
Calling Parent Methods With super
Inside a child method, super.methodName() calls the parent method.
class User {
describe() {
return "Regular user";
}
}
class Admin extends User {
describe() {
return `${super.describe()} with admin access`;
}
}
const admin = new Admin();
console.log(admin.describe());
// Regular user with admin accessThis is useful when you want to extend parent behavior instead of replacing it completely.
Inheritance Creates an "Is-A" Relationship
Use inheritance when the child really is a kind of parent.
Good:
Dog is an Animal.
Admin is a User.
SavingsAccount is a BankAccount.Questionable:
Car is an Engine.
User is a Database.
Order is an EmailSender.If the relationship is not "is-a", inheritance may be the wrong design.
Inherited Methods Use the Child Instance
class User {
constructor(name) {
this.name = name;
}
greet() {
return `Hello, ${this.name}`;
}
}
class Admin extends User {}
const admin = new Admin("Alice");
console.log(admin.greet()); // Hello, AliceThe method greet comes from User.
But this is the admin instance.
Inheritance Chains
Classes can inherit through multiple levels.
class Animal {}
class Mammal extends Animal {}
class Dog extends Mammal {}This works, but deep inheritance chains can become hard to understand.
Prefer simple inheritance.
Best Practices
Use inheritance for true "is-a" relationships.
Call super() before using this in child constructors.
Use method overriding carefully.
Use super.methodName() when extending parent behavior.
Avoid deep inheritance chains.
Consider composition when inheritance feels forced.
Common Mistakes
Mistake 1: Forgetting super() in a Child Constructor
class Admin extends User {
constructor(name) {
this.name = name; // ReferenceError
}
}Correct:
class Admin extends User {
constructor(name) {
super(name);
}
}Mistake 2: Using Inheritance for Code Sharing Only
Inheritance should model a meaningful relationship.
If you only want to reuse a helper function, use a separate function or composition.
Mistake 3: Overriding Methods Accidentally
If a child class defines a method with the same name as the parent, it replaces the parent method for that child.
Use clear method names and override intentionally.
Quick Check
What does this log?
class User {
constructor(name) {
this.name = name;
}
greet() {
return `Hello, ${this.name}`;
}
}
class Admin extends User {}
const admin = new Admin("Alice");
console.log(admin.greet());It logs:
Hello, AliceSummary
Inheritance lets one class extend another.
- Use
extendsto create a child class. - The child inherits parent methods.
- Use
super()to call the parent constructor. super()must run beforethisin child constructors.- Child classes can override parent methods.
super.methodName()calls a parent method.- Use inheritance for true "is-a" relationships.
- Avoid deep or forced inheritance.