Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extend base Array class in JavaScript

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?

like image 841
myol Avatar asked Sep 27 '18 03:09

myol


People also ask

Can we extend array class in JavaScript?

You CANNOT extend the Array Object in JavaScript. Instead, what you can do is define an object that will contain a list of functions that perform on the Array, and inject these functions into that Array instance and return this new Array instance. What you shouldn't do is changing the Array.

Can a class extend an array?

Arrays are objects but an array type is not a class and therefore can't be extended.

How do I extend a class in node JS?

By default, each class in Node. js can extend only a single class. That means, to inherit from multiple classes, you'd need to create a hierarchy of classes that extend each other. If you're with NPM v4 or lower, just append a -S to the install command to automatically add it to the dependencies in package.


1 Answers

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 applying the Array.prototype method:

<fnName>(...args) {
  return new ExampleArray(
    ...super.<fnName>.apply(this, args)
  );
}
like image 116
CertainPerformance Avatar answered Sep 20 '22 06:09

CertainPerformance