w3docs logo

JavaScript Extending Built-in Classes

Array, Map, and other built-in classes are extendable.

In the example below, NumsArray inherits from the native Array:

w3docs logo Javascript extending classes
// add another method to it (can do more) class NumsArray extends Array { isEmpty() { return this.length === 0; } } let arr = new NumsArray(1, 3, 6, 11, 27); console.log(arr.isEmpty()); // false let filterArr = arr.filter(item => item >= 10); console.log(filterArr); // 11, 27 console.log(filterArr.isEmpty()); // false

The most impressive thing is that built-in methods such as map, filter, and more - return new objects of literally the inherited type NumsArray.

Their internal implementation applies the constructor property of the object for that. So, in the example mentioned above, it looks like this:

arr.constructor === NumsArray

When you call arr.filter(), it internally generates the new array of results using arr.constructor and not basic Array.

Moreover, that behavior can be customized.

You can add to the class a unique static getter Symbol.species. In the case of its existence, it may return the constructor, which JavaScript will apply internally for creating new entities in the filter, the map, and more. If you want built-in methods such as map or filter to return ordinary arrays, you may return Array in Symbol.species, as follows:

w3docs logo Javascript extending classes
class NumsArray extends Array { isEmpty() { return this.length === 0; } // built-in methods will use this as the constructor static get[Symbol.species]() { return Array; } } let arr = new NumsArray(1, 3, 6, 11, 27); console.log(arr.isEmpty()); // false // filter creates new array using arr.constructor[Symbol.species] as constructor let filterArr = arr.filter(item => item > 10); // filterArr is not NumsArray, but Array console.log(filterArr.isEmpty()); // Error: filterArr.isEmpty is not a function

So, it can be assumed that now .filter returns Array. Hence, the extended functionality is not passed further.

Other collections, like Map and Set, work similarly using Symbol.species, also.

No Static Inheritance in Built-ins

There are different static methods for built-in objects. For example, Array.isArray, Object.keys, and more.

As you have already learned, native classes extend one another: Array extends Object.

Typically, when a class extends another one, the static and non-static methods are inherited. It was already explained in the chapter Static properties and methods. Please, take into account that built-in classes are an exception: they don’t inherit statics from one another.

For instance, both Date and Array inherit from Object, hence their instances have methods from Object.prototype. But Array.[[Prototype]] can’t reference Object, hence there isn’t any Array.keys() (or Date.keys()) static method.

The picture structure for Date and Object looks like this:

So, no link can be noticed between Date and Object. But Date.prototype inherits from Object.prototype.

It’s a notable inheritance difference between built-in objects in comparison to what is received with extends.

Do you find this helpful?