When Extending Array map is undefined

2020-04-14 08:04发布

问题:

I'm trying to extend Array so that I can add in my own additional functionality. I've read that extending Array.prototype can be dangerous, so I am trying to do it the correct way with class inheritance.

The issue I'm running into is that map is undefined. I can obviously work around this but I don't understand why as I am extending Array and therefore should have It's functionality?

export default class Array2 extends Array {
  constructor(items) {
    super(...items);
  }

  addOne() {
    return this.map((x)=>{
      return x+1;
    })
  }
}

let arry2 = new Array2 ([9, 1, 4, 0]).addOne();
console.log(arry2);

I expect to have Array2 (4) [10, 2, 5, 1] logged into the console but instead i get the following error thrown.

Uncaught TypeError: undefined is not a function

Edit Removing the constructor seems to fix the issue but does not explain why it fails when a constructor is present. especially when the constructor is just calling super.

回答1:

Debugging with

constructor(items) {
    console.log(...arguments);
    super(...items);
}

may shed some light on this. In map, a new array is created, of type Array2 - and it is calling the constructor with the desired length, 4 - just like a standard Array would support this. However, you are spreading the argument items into the super call, which will try to iterate the value 4 - and clearly it's not iterable, failing with "4[Symbol.iterator]() is not a function" (ok, that's what the message should have been).

To avoid this, use the standard constructor signature and just pass any arguments directly to super as they are. Or simply omit the constructor, as the default constructor will do this pass-through for you.

Use

export default class Array2 extends Array {
  addOne() {
    return this.map((x)=>{
      return x+1;
    })
  }
}

const array2 = Array2.from([9, 1, 4, 0]).addOne();
const array3 = Array2.of(9, 1, 4, 0).addOne();
console.log(array2, array3);

That's what of and from were made for.



回答2:

You used the spread operator on the wrong place. https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operator

I guess you would like to reach more parameters into the constructor function.

        class Array2 extends Array {
          constructor(items) {
            super(items); //here is the problem
          }

          addOne() {
            return this.map( (x) => {
              return x+1;
            } );
          }
        }




        let arry2 = Array2.from([2, 1, 4, 22]).addOne();
        console.log("arry2", arry2);