2

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.

5
  • does adding public keyword before the addOne() definition change anything? Commented Jan 30, 2018 at 15:43
  • Nope, but the addOne function works. I can loop through the values with a for loop, I just wanted to be functional and return a new array instead of editing the existing one. Commented Jan 30, 2018 at 15:47
  • you don't need to extend Array to do this. i would question why you're even making a separate adding function when a simple call to .map would work just fine. Commented Jan 30, 2018 at 15:53
  • This is funny. It looks like the internal map function fails... Proof Commented Jan 30, 2018 at 15:55
  • @Cruiser this is just a very simplified example of what i am trying to do. Commented Jan 30, 2018 at 15:58

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

6 Comments

What you have said makes sense in that it is a bad error description. Unfortunately running your code produces an error: Uncaught TypeError: Array2.from is not a constructor
Oops, I missed to remove the new.
This works now which is clever as i'm learning. Using the from method is there anyway I can pass other parameters into the constructor.
Yes, you can overload the constructor to use more constructors, but you always have to support the signature where a single integer is passed. (Not sure whether you even have to pass it through to super, but you must at least not cause an exception :P)
Reference to what this helped solve: github.com/StueyKent/svg-to-createjs-path
|
0

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);

2 Comments

Yes, eventually expanding on the constructor is the aim. Your code does not do what is expected though.
You need to remove the new and my example will work. If thought your constructor have had a unknown reason for me. So i don't touched it. Array2.from([9, 1, 4, 0]) will work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.