Extending Classes in JavaScript
Extending a class in JavaScript means creating a new class that inherits properties and methods from an existing one. The language provides the extends keyword and the super() call to make this work cleanly, whether you are building a small utility or a large framework. This guide covers the core syntax, how the prototype chain operates underneath, common pitfalls, and the patterns that keep inherited code readable.
More from this site
Keep reading the latest coverage
Basic Class Extension Syntax
Use extends to declare that one class derives from another. Inside the subclass constructor, call super() before accessing this. That single rule is the most common source of errors when extending classes in JavaScript.
class Animal { constructor(name) { this.name = name; } speak() { return `${this.name} makes a noise.`; } }class Dog extends Animal { constructor(name, breed) { super(name); this.breed = breed; } speak() { return ${this.name} barks.; } }
The subclass automatically gains access to every method defined on the parent, and overriding a method lets you customize behavior while still calling the parent version through super.method().
How the Prototype Chain Powers Extension
Under the hood, extends sets up a prototype chain. The subclass prototype object inherits from the parent prototype object, so method lookups walk up the chain until a match is found or null is reached. This is the same mechanism that function constructors used long before ES6 classes arrived.
- SubClass.prototype.__proto__ === ParentClass.prototype
- Instance lookups follow the prototype chain, then the instance itself.
- Object.getPrototypeOf(SubClass) === ParentClass is true for classes.
Extending Built-in Types
You can extend built-in types like Array, Map, or Error. The pattern is the same, but built-in constructors have special behavior around this. You must call super() and return the result, or the instance will not be properly initialized.
class MyArray extends Array { first() { return this[0]; } }const arr = new MyArray(1, 2, 3); arr.first(); // 1 arr.length; // 3
Built-in extension works in modern engines, but edge cases around species constructors and certain methods can still surprise developers.
Static Methods and Properties in Subclasses
Static methods are inherited alongside instance methods. A subclass can override a static method or call the parent static method with super.staticMethod(). Class fields declared with static belong to the class itself, not instances.
class Shape { static displayName = 'Shape'; static describe() { return `A ${this.displayName}`; } }class Circle extends Shape { static displayName = 'Circle'; }
Circle.describe(); // 'A Circle'
Common Gotchas When Extending Classes
- Forgetting super() in a constructor throws a ReferenceError.
- Calling this before super() is not allowed.
- Extending a class that does not return a compatible constructor can break inheritance.
- Overriding a method without calling super skips parent logic entirely.
Alternatives to Classical Extension
Not every situation needs inheritance. Mixins let you compose behavior by copying properties onto a class or object. Composition wraps an instance and delegates to it. Both approaches avoid the tight coupling that deep class hierarchies can create, and they are often easier to test and reason about than long chains of extended classes in JavaScript.