W3docs

JavaScript Class Inheritance

Learn JavaScript class inheritance with extends and super: the prototype chain, overriding methods and properties, and inheriting static methods.

Introduction to JavaScript Class Inheritance

Class inheritance is a fundamental concept in object-oriented programming that allows one class to inherit properties and methods from another class. In JavaScript, class inheritance is implemented using the extends keyword, providing a way to create a class as a derived class that inherits from a base class.

For more information about the basic syntax, see JavaScript: Classes and Basic Syntax.

This chapter covers how to create derived classes, override methods and properties, call into the parent with super, extend built-in classes like Array, and inherit static methods — plus the prototype chain that makes it all work under the hood.

How Inheritance Works: The Prototype Chain

The class keyword is syntactic sugar over JavaScript's prototypal inheritance. When you write class Circle extends Shape, the engine wires up two links:

  • Circle.prototype.__proto__ === Shape.prototype — so instance methods resolve up the chain.
  • Circle.__proto__ === Shape — so static methods are inherited too.

When you read a property or call a method on an object, the engine looks at the object itself first. If it isn't found there, it walks up the prototype chain — to Circle.prototype, then Shape.prototype, then Object.prototype, then null — stopping at the first match. This is exactly why an instance of Circle can call a method defined on Shape.

javascript— editable

Object.getPrototypeOf(obj) returns the next link in the chain (the standard, preferred way to inspect it). The legacy obj.__proto__ accessor points at the same object. Understanding this chain explains everything below: overriding works because a closer prototype shadows a farther one, and super works because it explicitly skips to the parent's prototype.

Creating a Derived Class

To create a class that inherits from another, we use the extends keyword:

javascript— editable

In this example, Circle extends Shape, meaning it inherits Shape's properties and methods, and at the same time providing methods of its own. Note that Circle does not define its own constructor. In JavaScript, derived classes without an explicit constructor automatically call super() with the same arguments passed to the derived class constructor.

Overriding Methods

Derived classes can override methods of their base classes to provide behavior specific to the subclass.

javascript— editable

Here, Circle overrides the print method to reflect its specific type.

Calling Parent Methods with super

You can also call a parent class's method from within the derived class using super.methodName(). This is useful when you want to extend the parent's behavior rather than completely replace it.

javascript— editable

Here, super.print() executes the parent's logic before adding the subclass-specific output.

A Realistic Override: Computing Area

Overriding shines when each subclass needs genuinely different behavior. Here a base Shape defines the shared interface, and each subclass overrides area() with its own real calculation. Calling area() on a Circle resolves to Circle.prototype.area, which shadows the base version.

javascript— editable

Notice that describe() is defined only on Shape, yet it calls this.area() and gets the subclass implementation. That is the prototype chain at work: this always refers to the actual instance, so method lookup starts from Circle or Rectangle.

Overriding Properties and Reading super.prop

super is not limited to methods — you can read a property defined on the parent prototype with super.prop, which is handy when a subclass wants to build on a parent's getter rather than replace it.

javascript— editable

Accessing Parent Constructor: super keyword

When a class extends another class, the constructor function of the derived class needs to call the parent's constructor using super() before it can use this. Here’s how super is used in constructors to ensure the parent class is initialized:

javascript— editable

Why super() Must Run Before this

In a derived class, the instance object is not created until super() runs — that is the parent constructor's job. Until then, this is in an uninitialized state, so touching it (reading, assigning, or even returning the object implicitly) throws a ReferenceError. This is a language rule, not a style preference.

javascript— editable

A related rule: if a derived class defines a constructor, it must call super() somewhere before it finishes, or the same ReferenceError is thrown. (A derived class with no explicit constructor is fine — JavaScript inserts constructor(...args) { super(...args); } for you.) Once super() returns, this is fully initialized and ready to use.

Inheriting Static Methods

Static members belong to the class itself, not to instances. Because extends also links Circle.__proto__ to Shape, derived classes inherit static methods and can call them directly. For more on declaring them, see JavaScript Static Properties and Methods.

javascript— editable

Inside a static method, this refers to the class it was invoked on, so Shape.create called as Circle.create constructs a Circle.

Multi-Level Inheritance

Chains can be more than two levels deep. Method lookup simply walks further up the prototype chain, and super always refers to the prototype one level above the class where the method is defined.

javascript— editable

Extending Built-in Classes

You can extend native classes such as Array, Error, or Map to create specialized versions that keep all built-in behavior while adding your own.

javascript— editable

The Symbol.species gotcha. Methods like map, filter, and slice return a new collection. By default they return an instance of your subclass (MyArray), not a plain Array — which is usually fine, but can surprise code that expects a real Array. You can opt back into plain arrays by overriding the static Symbol.species getter.

javascript— editable

For combining behavior from multiple sources (JavaScript has no multiple inheritance), see JavaScript Mixins.

Summary

Key takeaways:

  • Use extends to derive a class; it links both the prototype chain (instance methods) and the class itself (static methods) to the parent.
  • Method and property lookup walks the prototype chain, stopping at the first match — which is why a closer definition overrides a farther one. Inspect the chain with Object.getPrototypeOf().
  • In a derived constructor, call super() before this. Until super() runs, the instance is uninitialized and any use of this throws a ReferenceError.
  • Reach parent behavior explicitly with super.method() or super.prop, even when you've overridden it.
  • You can extend built-ins like Array — just watch the Symbol.species behavior when methods return new collections.

Next steps:

Practice

Practice
In JavaScript class inheritance, which statements are true?
In JavaScript class inheritance, which statements are true?
Was this page helpful?