The extends
keyword can be used to subclass custom classes as well as built-in objects.
Any constructor that can be called with new
(which means it must have the prototype
property) can be the candidate for the parent class.
function
OldStyleClass
(
)
{
this
.
someProperty =
1
;
}
OldStyleClass
.
prototype.
someMethod
=
function
(
)
{
}
;
class
ChildClass
extends
OldStyleClass
{
}
class
ModernClass
{
someProperty =
1
;
someMethod
(
)
{
}
}
class
AnotherChildClass
extends
ModernClass
{
}
The prototype
of the ParentClass
must be an Object
or null
.
function
ParentClass
(
)
{
}
ParentClass
.
prototype =
3
;
class
ChildClass
extends
ParentClass
{
}
Note: You would rarely worry about this in practice, because a non-object prototype
doesn’t behave as it should anyway. (It’s ignored by the new
operator.)
function
ParentClass
(
)
{
}
ParentClass
.
prototype =
3
;
console.
log
(
Object.
getPrototypeOf
(
new
ParentClass
(
)
)
)
;
extends
will set the prototype for both ChildClass
and ChildClass.prototype
.
class
ParentClass
{
}
class
ChildClass
extends
ParentClass
{
}
Object.
getPrototypeOf
(
ChildClass)
===
ParentClass;
Object.
getPrototypeOf
(
ChildClass
.
prototype)
===
ParentClass
.
prototype;
The right-hand side of extends
does not have to be an identifier. You can use any expression that evaluates to a constructor.
class
SomeClass
extends
class
{
constructor
(
)
{
console.
log
(
"Base class"
)
;
}
}
{
constructor
(
)
{
super
(
)
;
console.
log
(
"Derived class"
)
;
}
}
new
SomeClass
(
)
;
This is often useful to create mixins.
While the base class may return anything from its constructor, the derived class must return an object or undefined
, or a TypeError
will be thrown.
class
ParentClass
{
constructor
(
)
{
return
1
;
}
}
console.
log
(
new
ParentClass
(
)
)
;
class
ChildClass
extends
ParentClass
{
constructor
(
)
{
return
1
;
}
}
console.
log
(
new
ChildClass
(
)
)
;
If the parent class constructor returns an object, that object will be used as the this
value for the derived class when further initializing class fields. This trick is called “return overriding”, which allows a derived class’s fields (including private ones) to be defined on unrelated objects.