ddinchev
ddinchev

Reputation: 34673

JavaScript extend Array and add methods to child protype?

I want to create a js class that resembles simple music playlist (Array). I want to instantiate this playlist with IDs, each ID being a track ID in my database. I have interface like this:

function Playlist() {
    Playlist.prototype.current = 0;
    Playlist.prototype.prev = function() {
        if (this.current-1 < 0) {
            return null;
        }
        return this[--this.current];
    };
    Playlist.prototype.next = function() {
        if (this.current+1 >= this.length) { // length is index + 1
            return null;
        }
        return this[++this.current];
    };
    Playlist.prototype.seek = function(id) {
        for (i in this) {
            if (this[i] == id) {
                this.current = parseInt(i);
                return i;
            }
        }

        return false;
    };
    Playlist.prototype.getCurrent() {
            return this.current;
    };
};

The code above DOES NOT do what I want, because I imagine it as class that has it's method defined, that can be instantiated like this:

var newPlaylist = Playlist(2,3,5,10/* those are my ids */);

And currently the only way I've found is something like:

Playlist.prototype = new Array(2, 3, 5, 10/* those are my ids */);

Which does not make any sense since it can be instantiated as different objects. Any ideas are very welcome!

Upvotes: 0

Views: 67

Answers (2)

Bergi
Bergi

Reputation: 664936

Since you cannot subclass Array, you should build wrapper objects with your Playlist constructor:

Playlist = (function() {
    function Playlist(list) {
        this.list = list || [];
    }

    Playlist.prototype.current = 0;
    Playlist.prototype.prev = function() {
        if (this.current <= 0)
            return null;
        return this.list[--this.current];
    };
    Playlist.prototype.next = function() {
        if (this.current+1 >= this.length)
            return null;
        return this.list[++this.current];
    };
    Playlist.prototype.seek = function(id) {
        return this.list.indexOf(id);
    };

    return Playlist;
})();

Usage:

var newPlaylist = new Playlist([2,3,5,10]);

Upvotes: 1

Dmitry Manannikov
Dmitry Manannikov

Reputation: 1154

Best way - nested array;

function Playlist() {
    this.current = 0;
    this.list = Array.prototype.slice.call(arguments);;
};

Playlist.prototype.prev = function() {
    if (this.current-1 < 0) {
        return null;
    }
    return this.list[--this.current];
};
Playlist.prototype.next = function() {
    if (this.current+1 >= this.list.length) { // length is index + 1
        return null;
    }
    return this.list[++this.current];
};
Playlist.prototype.getCurrent = function() {
    return this.current;
};

var newPlaylist = new Playlist(2,3,5,10/* those are my ids */);

But you can't use list[i] to get element by index, but you just need add at() method to your class that provide similar functionality

PlayList.prototype.at(i) {
    return this.list[i];
}

Upvotes: 2

Related Questions