0

I want plain vanilla solution. I am writing a lot of for (var i = 0; i < someSize; i++) {...}

Please note that it's not for iterating an array or DOM nodes it's mainly for pure calculations.

I would like more functional approach because I am lazy. Something like: new Array(15).forEach(function(i, idx) { ... ... })

But this doesn't work.

When using underscore I used to write _.range(0,100,4).forEach(function(i, idx) { doSomethingWith(i); });

Please not that it may not be practical but I like to bend Javascript.

lukas.pukenis
  • 13,057
  • 12
  • 47
  • 81
  • 1
    possible duplicate of [For each in an array. How to do that in JavaScript?](http://stackoverflow.com/questions/9329446/for-each-in-an-array-how-to-do-that-in-javascript) – GSerg Feb 24 '14 at 08:05
  • Why make up an array just to iterate through a sequence of numbers? Why not just make a helper function that does the iteration (as in my answer)? I guess I'm puzzled why you think making a dummy array just so you can iterate a sequence of numbers is the desired solution here? – jfriend00 Feb 24 '14 at 08:54
  • You are right, I am creating a dummy array just because of `forEach`. It looks like your answer is the most suitable for me. – lukas.pukenis Feb 24 '14 at 08:57

2 Answers2

2

Not sure what you really want, but you can just have a generic iterator function that manages the loop counter for you:

function loop(start, stop, fn) {
   for (var i = start; i < stop; i++) {
       if (fn(i) === false) {
           return;
       }
   }
}

Then, you could use it like this:

loop(0, size, function(i) {
    // use i here
});

You could even make the start value optional (defaulting to zero if not present):

function loop(start, stop, fn) {
   if (!fn) {
      fn = stop;
      stop = start;
      start = 0;
   }
   for (var i = start; i < stop; i++) {
       if (fn(i) === false) {
           return;
       }
   }
}

loop(size, function(i) {
    // use i here
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
2

The reason this isn't working, seems to be because forEach isn't iterating the undefined values that are set when using the array constructor like that.

forEach works fine for arrays that actually have contents, as you will seen when you run code like this:

[1,2,3,4,5,6,7,8].forEach(function(){console.log(arguments)});

So, now, all you'd be looking for would be to properly initialize a new array, with contents.

This question on SO has some useful answers in that regard.
The shortest solution seems to be:

new Array(5+1).join('0').split('')

You can simply chain the forEach after that.

Or, you can whip up a prototype from one of the more upvoted answers in that question:

Array.prototype.init = function(value, length){
    return Array.apply(null, new Array(length)).map(function(){
        return value.valueOf();
    },value);
}

That allows you to do something like this:

[].init('foo', 3);
// ["foo", "foo", "foo"]
[].init(60, 4);
// [60, 60, 60, 60]
[].init({}, 3);
// [{},{},{}]
[].init(true, 9);
// [true, true, true, true, true, true, true, true, true]

You can of course chain a .forEach() after init().

(Actually, if you don't add this function to Array.prototype, you can just use init(), without the Array literal. That might be a "cleaner" solution)

Community
  • 1
  • 1
Cerbrus
  • 70,800
  • 18
  • 132
  • 147