Multiple for same i or not ? best practise

Hi,
I’ve a doubt
in a case like this:


for(var i = 0; i < array1Length; i++){
}
for(var i = 0; i < array2Length; i++){
}
for(var i = 0; i < array3Length; i++){
}

for best practise I should change the i name or not ?

Hi whisher,

I suggest you should keep it like

for(var i = 0; i < array1Length; i++){
}
for(var j = 0; j < array2Length; j++){
}
for(var k = 0; k < array3Length; k++){
}

by this way it will be easy for you to keep track of code

I believe this is one of those areas that is ‘personal taste’.
There was a time when conservation of the resources (memory) was paramount and, in that case, reuse of variables was a way to minimize the overhead.
That is no longer a consideration. Even with an interpreted language like Javascript, there are very few instances where the difference between creating a new [counter] variable and [re]using an existing one is even measurable!

It does make the code more readable (and, hence, easier to debug) if you use variable names that are descriptive and distinctive.
In that case, I would recommend something like this:


for(var people = 0; people < peopleArrayLength; people++){
}
for(var address = 0; address < addressArrayLength; address++){
}
for(var email = 0; email < emailArrayLength; email++){
}  

Personally, especially for counters, I simply reuse the same - short named - variable everywhere. Either ‘i’, as you have here or ‘x’ or ‘c’ (for counter).

Just to add my 2c worth:

I do the same as Thom.
If I declare a throw-away variable, for example for a counter, I always call it i.

If I nest for loops then I increment the variable accordingly.
E.g.

for(var i = 0; i < array1Length; i++){
}
for(var i = 0; i < array2Length; i++){
}
for(var i = 0; i < array3Length; i++){
}

But:

for(var i = 0; i < array1Length; i++){
  for(var j = 0; j < array2Length; j++){
    for(var k = 0; k < array3Length; k++){
    }
  }
} 

Not sure if that is best practise, but I cannot think of any reason (apart from readability, as Thom mentioned above) why it might be a bad thing.

Thanks everybody for the feedback.

If you move all the variable declarations to the top of their scope then you will not have the var being repeated multiple times in the code unnecessarily. For example:

(function() {"use strict";
var i, array1Length, array2Length, array3Length;

....

for(i = 0; i < array1Length; i++){ 
} 
for(i = 0; i < array2Length; i++){ 
} 
for(i = 0; i < array3Length; i++){ 
}  

....

})();

One of my favorite patterns (especially in Javascript) is this:


var i = {length of array}
while (i--) {
  //do something important with the array using the index 'i'
}

The only [perhaps undesirable] effect of this is that the array is iterated in reverse order. But the syntax is small and concise.

My first thought about that is “is there a special reason why you’re iterating over it in reverse order?”
Closely followed by “Is he wanting to optimising for speed? What is it in this loop that has such a high demand?”
Most often followed up by “Oh, the code doesn’t need such performance enhancements. He’s doing this instead to demonstrate that he knows about such techniques.”

So in summary, what is the code saying to the person who will be reading it?

In terms of loops though, I agree with Felgall in all parts, except for the parenthesis hanging off the end.

I prefer to use:


(function () {
    ...
}());

So that the normal consistent structure of a function is maintained, where the braces are directly followed by the parenthesis for arguments.

As an aside, I was watching Crockford yesterday lampoon the use of i++ instead of i += 1.

Anyhow, I’ve been learning about the different ways to invoke functions, and am surprised at how many ways there are to call functions. I’ve been intrigued over the difference between


(function () {
    ...
}());

and


(function () {
    ...
})();

Is there a subtle difference in meaning? It seems weird that it can be either way around.

In both cases, the function is changed from being a function declaration to a function expression, by wrapping parenthesis around the whole lot.
Due to it now being a function expression, it can also be invoked at the same time, which gives us a self-invoking (or executing) function.

With the first example the () parenthesis invokes the function, all of which are wrapped by the parenthesis that allow it to be a function expression.
With the second example, the () invokes the whole lot that’s wrapped by the outer parenthesis.

The outcome for both are exactly the same, so whichever one you use tends to come down to a matter of personal style and taste. Or it can be due to a style guide that you follow.

For me, I prefer the former, because it’s more consistent with how other function expressions are used.


var invokedFunction = function () {
    ...
}();

Bad developer! Bad! Bad! :wink: Making extraneous loops where they are not necessary…that could also cause problems depending on what happens inside the loops - you could end up with different results. :shifty:

I would also agree with felgall and paul - declare the variable once and reuse it. Declaring it multiple times is a waste of resources (CPU/memory/time, etc). If you can reuse it, then by all means do so. This is one lesson that I WISH the educators of today would reintroduce - it’s one of the things I learned early on (back in the mainframe days). Coding for speed and efficiency will usually end up with the most elegant solution.

Edit:

OK - I now see why you did what you did - his question and his code pattern didn’t match. The OP asked about nested loops, but the code in question isn’t nested…

Bang to rights! :slight_smile:

Man, the kids today with their quad-core, hyperthreading i7 processors and their 20GB of Corsair DDR3 RAM!
I just want to go back to the good old days of huge mainframes with 2000+ vacuum tubes.
Days when micro-optimization made a difference!
:wink:

On a serious note, this is very true.

Just out of interest, you’re not saying that there’s anything wrong with nested for loops, are you?

Yeah because like Guido, he thinks we’re somehow capable of reading complicated code but will fall into fits of confusion if someone does i++. I honestly don’t understand the thinking there, and I strongly miss my i++/i-- in Python.

I like the plus because it looks funky:
+function(){foobarbaz;}();

http://jsperf.com/self-invoking-function

Backwards is great when you’re screwing with the array as you go, like, deleting stuff. That way, your index number doesn’t change for the remaining items.

Well, I heard John Resig say JS finally has list comprehensions as stolen from Python, which means you don’t necessarily have to have nested for loops (but in Python, the compiler is optimised for them so they’re almost always a better choice than actual nested for loops, unless you think readability is an issue).

pseudo:


for(var i = 0; i < array1Length; i++){
  if (array1[i].has-a.Foo) {
      for(var j = 0; j < array2Length; j++){
     }
  }
}

becomes
[j for i in array1 if Foo in i for j in array2]

i think.

I wouldn’t mind having these available for my (non-nested) for loops, since often in my non-libraried JS I’m making throwaway loops all the time to separate out some DOM elements or whatever.

I know you were joking, but it’s amazing how convoluted I see things nowadays - and how people are so amazed that just simplifying the logic makes the app work faster…the copy/paste method of developing sigh

Nope, not at all. There’s nothing wrong with them at all.

The reason why I replied was I noticed your code would create a different result than his sample. His sample had three distinct loops, which ran separately - yours were nested.

his:



for(var i = 0; i < array1Length; i++){   echo("i = " & i);}
for(var i = 0; i < array1Length; i++){ [FONT=Verdana]  echo("i = " & i);[/FONT][FONT=Verdana]}[/FONT]

for(var i = 0; i < array1Length; i++){ [FONT=Verdana]  echo("i = " & i);[/FONT]
}[FONT=Verdana]

[/FONT]

Yours



for(var i = 0; i < array1Length; i++){   for(var j = 0; j < array2Length; j++){     for(var k = 0; k < array3Length; k++){        echo("k = " & k);    }  }}

Results would be totally different - but then I noticed his original post, which could be read to be asking about nesting the loops, which your answer would work for.

Cool.

Ah okay, then I fear we got our wires crossed a little.
What I actually meant was that I would personally leave the code just as the OP had it:

for(var i = 0; i < array1Length; i++){ console.log("loop 1"); }
for(var i = 0; i < array2Length; i++){ console.log("loop 2"); }
for(var i = 0; i < array3Length; i++){ console.log("loop 3"); }

(Although in hindsight, I would take on board felgall’s and Paul’s suggestions)

However, jimmybrion had previously suggested changing the variable names to ‘i’, ‘j’ and ‘k’.
This is by no means wrong, but I was making the point that I would only do this if the loops were nested:

for(var i = 0; i < array1Length; i++){ 
  for(var j = 0; j < array2Length; j++){ 
    for(var k = 0; k < array3Length; k++){ 
    }
  }
}

And further on from there, it would be useful to consider changing them from i,j,k if the named counterparts result in making the intention of the code easier to understand.

Because it is a standard practice to use i as a loop index, if the intention of the loop is for something else then that a good time to to use something else other than i, so that people don’t misunderstand what the index is being used for.

Just to clarify, do you mean like Thom’s example?

for(var people = 0; people < peopleArrayLength; people++){ ... }
for(var address = 0; address < addressArrayLength; address++){ ... }
for(var email = 0; email < emailArrayLength; email++){ ... }

I’ve just been reading up on this. It seems they’re called Array Comprehensions and are available as of JavaScript 1.7

This effectively means that instead of this:

var nums = [1,2,3,4,5,6,7,8,9], greaterThanFive = [];
for(var i=0; i < nums.length; i++){
  if (nums[i] > 5){
    greaterThanFive.push(nums[i]);
  }
}

I can write this:

var nums = [1,2,3,4,5,6,7,8,9];
var greaterThanFive = [i for (i of nums) if (i > 5)]

And instead of this:

var nums = [[1,2,3],[4,5,6],[7,8,9]], greaterThanFive = []
for(var i=0; i < nums.length; i++){
  for(var j=0; j < nums[i].length; j++){
    if (nums[i][j] > 5){
      greaterThanFive.push(nums[i][j]);
    }
  }
}

I can write:

var nums = [[1,2,3],[4,5,6],[7,8,9]]
var greaterThanFive = [j for (i of nums) for (j of i) if (j > 5)]

I didn’t know you could do that. Thanks, poes.

N.B. They’re horrid examples, I know, and could certainly be written better. I just wanted to play around with the comprehension thingies.

Yes, something like that. Good examples tend to be difficult to come up with because as soon as they’re created, other forms of structures are seen to be better.

But for the sake of example, I’m meaning something like this:


for (width = 0, width = maxWidth; width += 1) {
    for (height = 0, height = maxHeight; height += 1) {
        doSurfaceThingAt(width, height);
        for (depth = 0, depth = maxDepth; depth += 1) {
            doSomethingAt(width, height, depth);
        }
    }
}

So that you end up with

doSomethingAt(width, height, depth);

Instead of

doSomethingAt(I, j, k);

Or even

doSomethingAt(x, y, z);

Because is y gong vertical, or is it an x/y plane on the ground? Such questions are easily answered with more expressive names.

I think the use of i, j etc for loop variables goes back to ForTran where i was the first single character integer variable name - all the earlier letters of the alphabet were for floating point.

Best practice is to use one var statement at the top of the function to declare all the variables at the spot where JavaScript itself will actually declare them. That way the code matches the way it will run and it is far easier to see which variables the function uses as they are all together in one place at the top of the function.

Thanks for the explanation, Paul. It’s also nice to know the names ‘function expression’, as now I can look it up. (Was having trouble working out what that syntax was called.)

You can watch it here: http://www.youtube.com/watch?v=taaEzHI9xyY&t=50m50s . I guess he is talking from a high level here, but still, he makes a fair point (that x += 1 isn’t necessarily exactly the same as x++). I also like his little joke, that “the last popular language with point arithmetic was C++, a language so bad it was named after this operator”.

I like the plus because it looks funky:
+function(){foobarbaz;}();

Egad, another one? I hadn’t come across that one.