1

I try to create a custom Array class by extending the generic Array one. On this class I want to create a custom find / filter. When I call the custom find it works well, but when I call the filter I get a problem with the iterator. There is my code

class MyClass extends Array {
  constructor(inArray){
    super();
    this.push(...inArray);
  }

  myFind(callback) {
    return this.find(callback);
  }

  myFilter(callback) {
    return this.filter(callback);
  }
}
//Works
console.log(new MyClass(["a","b"]).myFind(item => item === "a"));
//Do not work
console.log(new MyClass(["a","b"]).myFilter(item => item === "a"));
miorey
  • 512
  • 5
  • 12
  • 1
    Possible duplicate of [Why are Objects not Iterable in JavaScript?](https://stackoverflow.com/questions/29886552/why-are-objects-not-iterable-in-javascript) – rafaelcastrocouto Nov 27 '18 at 11:45
  • 1
    No because my class extends `Array`. This behavior is due to `new this.constructor(0);` called in filter prototype as @javimovi and @Jonas Wilms explained below. – miorey Nov 27 '18 at 12:36

2 Answers2

3

The difference is, that .filter(...) creates a new array. And that array is very special, as it got the same type as the array it is called on:

 (new MyClass(["a", "b"])).filter(/*...*/) // MyClass(...)

so when you call filter, it calls the arrays constructor by passing the arrays length first:

 Array.prototype.filter = function(cb) {
  const result = new this.constructor(0); // <---
  for(const el of this) 
    if(cb(el) result.push(el);
  return result;
};

Now that constructor is:

 constructor(inArray){ // inArray = 0
   super();
   this.push(...inArray); // ...0
}

and spreading 0 is impossible. To resolve that, make the constructor behave just as the arrays constructor, or just don't add your own constructor.

Jonas Wilms
  • 106,571
  • 13
  • 98
  • 120
2

Try add:

class MyClass extends Array {
  constructor(inArray){
    super();
    if(inArray !== 0 ) this.push(...inArray); // Condition
  }

  myFind(callback) {
    return this.find(callback);
  }

  myFilter(callback) {
    return this.filter(callback);
  }
}

The problem is that it is very dangerous to overwrite the ARRAY class constructor, the function of the filter is to create an empty array and then fill it with the matches it finds, so when creating an empty array inArray === 0, this causes this.push (... inArray) give an error.

javimovi
  • 358
  • 2
  • 10