While trying to think of ways to quickly build an iterable I came across this bit of code that creates a constructor that inherits from Array
class MovieCollection extends Array {
constructor(name, ...items) {
super(...items);
this.name = name;
}
add(movie) {
this.push(movie);
}
topRated(limit = 10) {
return this.sort((a, b) => (a.stars > b.stars ? -1 : 1)).slice(0, limit);
}
}
const movies = new MovieCollection('Fav Movies',
{ name: 'Star Wars', stars: 10 },
{ name: 'Aliens', stars: 8 },
{ name: 'Spaceballs', stars: 9 },
{ name: 'Source Code', stars: 8 }
);
movies.add({ name: 'Titanic', stars: 5 });
It is cool that I get all of the methods that I love like map, filter, reduce, plus I can add my own properties and methods and it is iterable so that I can do this:
for (let movie of movies) {
console.log(movie);
}
console.log(movies);
The problem I’m having is trying to implement my own solution without es6 classes in a pattern that will pass those arguments to the super. In the code above I see that the super is passed all of movies in a clever way. But when I create my solution I can’t think of any way to pass the movies to the super ‘Array’- heck, I didn’t even call the super in the subclass.
function MovieCollection(name) {
for (var i = 1; i < arguments.length; i++) {
this.push(arguments[i]);
}
this.name = name;
//i didn't Array.call(this) since I think I didn't need to
}
MovieCollection.prototype = Object.create(Array.prototype);
MovieCollection.prototype.add = function(movie) {
this.push(movie)
}
var movies = new MovieCollection('Fav Movies',
{ name: 'Star Wars', stars: 10 },
{ name: 'Aliens', stars: 8 },
{ name: 'Spaceballs', stars: 9 },
{ name: 'Source Code', stars: 8 }
);
movies.add({ name: 'Titanic', stars: 5 });
//to show it is still iterable
for (var movie of movies) {
console.log(movie);
}
console.log(movies);
So how is it that in the class pattern they passed arguments to super as if super actually is called with the arguments:
super(...items);
I changed it to the code below and it works just fine
class MovieCollection extends Array {
constructor(name, ...items) {
//didn't pass the stuff to super and works fine but I get an error if I don't call super
super();
[...items].forEach( (item) => this.push(item))
this.name = name;
}
add(movie) {
this.push(movie);
}
topRated(limit = 10) {
return this.sort((a, b) => (a.stars > b.stars ? -1 : 1)).slice(0, limit);
}
}
const movies = new MovieCollection('Fav Movies',
{ name: 'Movie', stars: 10 },
{ name: 'Star Trek', stars: 1 },
{ name: 'Virgin', stars: 7 },
{ name: 'King of the Road', stars: 8 }
);
movies.add({ name: 'Titanic', stars: 5 });
for (var movie of movies) {
console.log(movie);
}
console.log(movies);
Why do you have to call super if the es5 pattern didn’t have to and does Array really get called with the arguments?
thanks in advance for any advice/help