0

Is there any way to keep index from being a global variable in this example:

var arr = [1, 2, 3, 4, 5];
var index = 0;
function run() {
    console.log(arr[index]);
    if(++index == arr.length) index = 0;
}

It seems like it has to be global in order to be checked each time but I was wondering if there are any clever tricks to get around the global variables.

Startec
  • 12,496
  • 23
  • 93
  • 160

2 Answers2

4

You can use a closure (here created using an IIFE):

var run = (function() {
    var index = 0;
    return function run() {
        console.log(arr[index]);
        if(++index == arr.length) index = 0;
    };
}());

But since arr is global as well, it's not a huge improvement IMO. It would be better (from a code organizational point of view) to pass the array as argument to the function, or also define it inside the IIFE, if it is supposed to be static data.

Alternatively, you could make the index a property of the function, since functions are just objects. This has the disadvantage(?) that the index would be mutable from the outside (and you make the implementation of the function dependent on the function's name, which is also mutable (which could be solved by using a named function expression instead)):

function run() {
    console.log(arr[run.index]);
    if(++run.index == arr.length) run.index = 0;
}
run.index = 0;
Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • No need to reset the counter, right? `arr[i++ % arr.length]` – elclanrs Jul 09 '14 at 02:46
  • Right, unless there is a chance that `i` overflows. – Felix Kling Jul 09 '14 at 02:48
  • I thought in this syntax you always ad to put the ending `()` very last. I.e. `var run = (function(){ console.log('ran'); })()` – Startec Jul 09 '14 at 03:42
  • And what do you mean by change that `i` "overflows". Also, I have heard conflicting views on how fast using `%` vs. `if` is: Do you have a stance on the issue? – Startec Jul 09 '14 at 03:49
  • 1
    @Startec: I wouldn't worry about performance at this point, especially if you are doing DOM manipulation somewhere as well. The maximum integer value that JS can represent precisely is `9007199254740992`. Adding to this value won't produce any meaningful results anymore, so the modulus operation wouldn't work correctly either. But doubt that `run` will be executed `9007199254740992` times in one page load, so you'll be fine. I just mentioned it for completeness ;) – Felix Kling Jul 09 '14 at 03:58
1

In general, one can avoid variables in Javascript via various namespace patterns discussed here.

For instance, the following is an example of a revealing module pattern which could be used to prevent your index variable as well as the rest of your Javascript objects from being in the global scope:

var namespace = (function () {

    // defined within the local scope
    var arr = [1, 2, 3, 4, 5];
    var index = 0;
    function run() {
       console.log(arr[index]);
        if(++index == arr.length) index = 0;
    }

    return {
        run: run
    }
})();

One could than invoke the run method by saying namespace.run();

m.casey
  • 2,579
  • 17
  • 10