I have a custom array class that extends the base array class. I have a custom method for ease of use
export class ExampleArray extends Array {
includesThing(thing) {
...
return false
}
}
However the existing methods of filter
, map
etc return an instance of an array. I would like to return an instance of ExampleArray
with these methods.
I can find the interface for these methods, but not their implementation. How do I call the parent method and return my custom EampleArray instead? Something like the following
export class ExampleArray extends Array {
filter() {
result = Array.filter()
array = new ExampleArray()
array.push(...result)
return array
}
Or is this even the correct way to extend an Array to make a custom array?
You will need to shadow the existing .filter
and .map
so that, when called on an instance of ExampleArray
, your new functions will be called, rather than the Array.prototype
functions. Inside ExampleArray
, you can access super.map
and super.filter
in order to get to the Array.prototype
methods. For example:
class ExampleArray extends Array {
constructor(...args) {
super(...args);
}
hasMoreThanTwoItems() {
// example custom method
return this.length > 2;
}
isExampleArray() {
return true;
}
// Shadow Array.prototype methods:
filter(...args) {
return new ExampleArray(
// Spread the result of the native .filter into a new ExampleArray instance:
...super.filter.apply(this, args)
);
}
map(...args) {
return new ExampleArray(
...super.map.apply(this, args)
);
}
}
const exampleArray = new ExampleArray(3, 4, 5, 6, 7);
// true, filtering will result in 3 items
console.log(
exampleArray
.filter(e => e > 4)
.hasMoreThanTwoItems()
);
// false, filtering will result in zero items
console.log(
exampleArray
.filter(e => e > 10)
.hasMoreThanTwoItems()
);
// true, is an ExampleArray
console.log(
exampleArray
.map(e => e * 2)
.isExampleArray()
);
Note that there are also other Array methods which return arrays, including splice
, slice
, and (experimental) flat
and flatMap
. If you want those to return a custom class instantiation rather than the default Array
instance, follow the same pattern: shadow the Array.prototype
function name, and return a new ExampleArray
populated with the result of apply
ing the Array.prototype
method:
<fnName>(...args) {
return new ExampleArray(
...super.<fnName>.apply(this, args)
);
}