Is it bad practice to use the same variable name in multiple for-loops?

JavascriptFor LoopJslintJshint

Javascript Problem Overview


I was just linting some JavaScript code using JSHint. In the code I have two for-loops both used like this:

for (var i = 0; i < somevalue; i++) { ... }

So both for-loops use the var i for iteration.

Now JSHint shows me an error for the second for-loop: "'i' is already defined". I can't say that this isn't true (because it obviously is) but I always thought this wouldn't matter as the var i is only used in that specific place.

Is it bad practice to use for-loops this way? Should I use a different variable for each for-loop in my code like

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }

Or is this on e of the errors I can ignore (because it doesn't break my code, it still does what it is supposed to do)?

JSLint btw. stops validating at the first for loop because I don't define var i at the top of the function (that's why I switched to JSHint in the first place). So according to the example in this question: https://stackoverflow.com/questions/6803305/should-i-use-jslint-or-jshint-javascript-validation/10763615#10763615 – I should use for-loops like this anyway to confirm JSLint:

...
var i;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
...
//for-loop 2
for (i = 0; ...; i++) { ... }

This also looks good to me, because this way I should avoid both errors in JSLint and JSHint. But what I am uncertain about is if I should use a different variable for each for-loop like this:

...
var i, j;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
//for-loop 2
for (j = 0; ...; j++) { ... }

So is there a best practice for this or could I just go with any of the codes above, meaning I choose "my" best practice?

Javascript Solutions


Solution 1 - Javascript

Since variable declarations are hoisted to the top of the scope in which they appear the interpreter will effectively interpret both versions in the same way. For that reason, JSHint and JSLint suggest moving the declarations out of the loop initialiser.

The following code...

for (var i = 0; i < 10; i++) {}
for (var i = 5; i < 15; i++) {}

... is effectively interpreted as this:

var i;
for (i = 0; i < 10; i++) {}
for (i = 5; i < 15; i++) {}

Notice that there is really only one declaration of i, and multiple assignments to it - you can't really "redeclare" a variable in the same scope.

To actually answer your question...

> is there a best practice for this or could I just go with any of the codes above?

There are varying opinions on how best to handle this. Personally, I agree with JSLint and think the code is clearer when you declare all variables together at the top of each scope. Since that's how the code will be interpreted, why not write code that looks as it behaves?

But, as you've observed, the code will work regardless of the approach taken so it's a style/convention choice, and you can use whichever form you feel most comfortable with.

Solution 2 - Javascript

It has been mentioned only in the comment by @TSCrowder: If your environment supports it (Firefox, Node.js), in ES6 you can use let declaration

//for-loop 1
for (let i = 0; ...; i++) { ... }

//for-loop 2
for (let i = 0; ...; i++) { ... }

which limits the scope to within the for-loop. Bonus: JSHint stops complaining.

Solution 3 - Javascript

Variables in javascript are function scoped (not block scoped).

When you define var i in a loop, it remains there in loop and also in the function having that loop.

See below,

function myfun() {
    //for-loop 1
    for (var i = 0; ...; i++) { ... }

    // i is already defined, its scope is visible outside of the loop1.
    // so you should do something like this in second loop.

    for (i = 0; ...; j++) { ... }

    // But doing such will be inappropriate, as you will need to remember
    // if `i` has been defined already or not. If not, the `i` would be global variable.
}

Solution 4 - Javascript

The reason JSHint shows the error is because in JS variable scope is function and variable declarations are hoisted to the top of the function.

In Firefox you can use let keyword to define block scope, but is not currently supported by other browsers.

The let keyword is included ECMAScript 6 specification.

Solution 5 - Javascript

I know this question has been answered, but if you want super for loops, write them like this:

var names = ['alex','john','paul','nemo'],
    name = '',
    idx = 0,
    len = names.length;

for(;idx<len;++idx)
{
    name = names[idx];
    // do processing...
}

A couple of things going on here...

  1. The array length is being stored in len. This stops JS evaluating names.length every iteration

  2. The idx increment is a PRE-INCREMENT (e.g. ++idx NOT idx++). Pre-increments are natively faster than Post-increments.

  3. The storing of a reference to name. This is optional but recommended if you'll be using the name variable a lot. Every call to names[idx] requires finding the index in the array. Whether this search be a linear search, tree search or hash table, the find is still happening. So store a reference in another variable to reduce lookups.

Finally, this is just my personal preference, and I have no proof or any performance benefits. However I always like initialising variables to the type they're going to be e.g. name = '',.

Solution 6 - Javascript

The best practice is to reduce the scope of variables, so the best way to declare iteration variable for the loops is

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }

I know the scope of the variables declared with var but I am taking about code readability here.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTimGView Question on Stackoverflow
Solution 1 - JavascriptJames AllardiceView Answer on Stackoverflow
Solution 2 - Javascriptserv-incView Answer on Stackoverflow
Solution 3 - JavascriptJashwantView Answer on Stackoverflow
Solution 4 - JavascriptCorneliuView Answer on Stackoverflow
Solution 5 - JavascriptAlexMorley-FinchView Answer on Stackoverflow
Solution 6 - JavascriptNikolay KostovView Answer on Stackoverflow