How to move to prev/next element of an array

If you want to keep the list as an Array, you'll have to change its [[prototype]] to make it look like an iterable collection:

Array.prototype.next = function() {
    return this[++this.current];
};
Array.prototype.prev = function() {
    return this[--this.current];
};
Array.prototype.current = 0;

Now every Array will have the methods prev and next, and the current property, which points to the "current" elements. A caveat: the current property can be modified, thus leading to impredictable results.

Post scriptum: I don't recommend to make prev and next return false when the index is out of range. If you really want to, you can change the methods to something like:

Array.prototype.next = function() {
    if (!((this.current + 1) in this)) return false;
    return this[++this.current];
};

UPDATE mid-2016

I'm updating this answer because it seems it's still receiving views and votes. I should have clarified that the given answer is a proof of concept and in general extending the prototype of native classes is a bad practice, and should be avoided in production projects.

In particular, it's not much because it's going to mess with for...in cycles - which should always be avoided for arrays and it's definitely a bad practice for iterating through their elements - and also because since IE9 we can reliably do this instead:

Object.defineProperty(Array.prototype, "next", {
    value: function() { return this[++this.current]; },
    enumerable: false
});

The main problem is that extending native classes is not future-proof, i.e. it may happen that ECMA will introduce a next method for arrays that will probably be incompatible with your implementation. It already happened even with very common JS frameworks - the last case was MooTools' contains array extension which led ECMA to change the name to includes (bad move, IMO, since we already have contains in DOMTokenList objects like Element.classList).

That being said, it's not that you must not extend native prototypes, but you should be aware of what you're doing. The first advice I can give you is to choose names that won't clash with future standard extensions, e.g. myCompanyNext instead of just next. This will cost you some code elegance but will make you sleep sound.

Even better, in this case you can effectively extend the Array class:

function MyTraversableArray() {
    if (typeof arguments[0] === "number")
        this.length = arguments[0];
    else this.push.apply(this, arguments);

    this.current = 0;
}
MyTraversableArray.prototype = [];
MyTraversableArray.prototype.constructor = MyTraversableArray;
MyTraversableArray.prototype.next = function() {
    return this[++this.current];
};
MyTraversableArray.prototype.prev = function() {
    return this[--this.current];
};

In ES6, moreover, it's easier to extend native classes:

class MyTraversableArray extends Array {
    next() {
        return this[++this.current];
    }
}

Alas, transpilers have a hard time with native class extensions, and Babel removed its support. But it's because they can't exactly replicate some behaviours which have no influence in our case, so you can stick with the above old ES3 code.


I generally recommend against adding things to Array.prototype because of the amount of really bad JavaScript out there. For instance, if you set Array.protoype.next = function () {} and someone has the following code, then there's a problem:

var total = 0, i, myArr = [0,1,2];
for(i in myArr) {
    total += myArr[i];
}
total; //is probably "3next"

This bad use of for-in loops is disturbingly common out there. So you're asking for trouble by adding to Array's prototype. However, it's pretty easy to build a wrapper to do what you're looking to do:

var iterifyArr = function (arr) {
    var cur = 0;
    arr.next = (function () { return (++cur >= this.length) ? false : this[cur]; });
    arr.prev = (function () { return (--cur < 0) ? false : this[cur]; });
    return arr;
};

var fibonacci = [1, 1, 2, 3, 5, 8, 13];
iterifyArr(fibonacci);

fibonacci.prev(); // returns false
fibonacci.next(); // returns 1
fibonacci.next(); // returns 1
fibonacci.next(); // returns 2
fibonacci.next(); // returns 3
fibonacci.next(); // returns 5
fibonacci.next(); // returns 8
fibonacci.prev(); // returns 5
fibonacci.next(); // returns 8
fibonacci.next(); // returns 13
fibonacci.next(); // returns false

A couple notes:

First of all, you probably want to have it return undefined instead of false if you go past the end. Secondly, because this method hides cur using a closure, you don't have access to it on your array. So you might want to have a cur() method to grab the current value:

//Inside the iterifyArr function:
    //...
    arr.cur = (function () { return this[cur]; });
    //...

Finally, your requirements are unclear on how far past the end the "pointer" is maintained. Take the following code for example (assuming fibonacci is set as above):

fibonacci.prev(); //false
fibonacci.prev(); //false
fibonacci.next(); //Should this be false or 1?

In my code, it would be false, but you might want it to be 1, in which case you'd have to make a couple simple changes to my code.

Oh, and because it the function returns arr, you can "iterify" an array on the same line as you define it, like so:

var fibonacci = iterifyArr([1, 1, 2, 3, 5, 8, 13]);

That might make things a bit cleaner for you. You can also reset the iterator by re-calling iterifyArr on your array, or you could write a method to reset it pretty easily (just set cur to 0).