Declaring var inside Javascript for loop declaration

10,401

Solution 1

These are exactly the same. All local variables in javascript have function scope which means they are alive for the entire function they are declared in. This is often counter intuitive at first as most curly brace languages scope the life time of the variable to the block they are declared in.

A portion of Javascript developers very much prefer the second form. The rationale is that since all variables have function scope, you should declare them at the function level to make the life time explicit even for those not familiar with Javascript. This is just a style though and by no means a hard rule

EDIT

Note that with the introduction of ES6 let, you can now use let inside your loop for real block-scoped variable more details

for(let i = 1; i <= 5; i++) {
   setTimeout(function(){
       console.log('Value of i : ' + i);
   },100);
}

Solution 2

The problem with declaring with var in the loop header is that it's deceptive. It looks like you're declaring a variable whose scope is limited to the for loop, when it actually exists everywhere within the function - including before the declaration:

var i = 1;
function foo() {
   console.log(i);                     // 'undefined'
   for (var i=1; i<100; ++i) {
   }
}

Even though the console.log call occurs before the declaration of the local i, it is still in scope for it because it's inside the same function. So the local i, which has not yet had any value assigned to it, is what gets passed to log. This can be surprising; it's certainly not obvious to anyone who's not familiar with Javascript scoping rules.

Starting with ECMAScript 2015, there is a better way to declare variables: let. Variables declared with let are local to the block containing them, not the entire function. So this version of the above code will print 1 as intended:

let i=1; // could use var here; no practical difference at outermost scope
function foo() {
  console.log(i);               // 1
  for (let i=1; i<100; ++i) {
  }
}

So best practice in modern Javascript is to declare variables with let instead of var. However, if you are stuck with a pre-ECMAScript 2015 implementation, it's a little less confusing to declare all variables at the top of the function, rather than waiting till first use.

Solution 3

There's no difference, but I prefer the second way (per Crockford) because it explicitly shows that the variable to available outside of the for loop:

function() {
    for(var i=0; i<7; i++) {
        // code
    }

    // i is still in scope here and has value 7
}
Share:
10,401
Benjamin Allison
Author by

Benjamin Allison

Updated on June 05, 2022

Comments

  • Benjamin Allison
    Benjamin Allison almost 2 years

    I'm sure I've read a discussion on SO about this but can't find it. Simply, are there cons to declaring a for loop's increment inside the loop's declaration? What is the difference between this:

    function foo() {
        for (var i=0; i<7; i++) {
            // code
        }
    }
    

    ...and this:

    function foo() {
        var i;
        for (i=0; i<7; i++) {
            // code
        }
    }
    

    Since JS has function scope, either should be fine, right? Are there edge cases where the former approach would cause problems?

    If they are identical, why is Crockford/JSLint all, "No way dawg," about it?

  • Benjamin Allison
    Benjamin Allison about 12 years
    So as long as you're familiar with Js's handling of scope, then all's well.
  • Mark Reed
    Mark Reed about 12 years
    Not a very helpful answer; the question is, given that they are functionally equivalent, why the rule in JSLint? JSLint is astonishingly picky about a wide variety of things, whose importance to you may vary widely, but there is method to its madness.
  • Benjamin Allison
    Benjamin Allison about 12 years
    Lol it means something... maybe not much but for a noob like me it helps to establish good habits.
  • Mark Reed
    Mark Reed about 12 years
    @Rob: feel free to ignore it, but the OP specifically asked why it flagged this behavior. Your disdain for the software doesn't mean they don't deserve an answer to the question.
  • Rob
    Rob about 12 years
    JSLint can be helpful but it is overly opinionated and too many people seem to think that if you don't pass jslint validation then your code sucks.
  • 4castle
    4castle almost 8 years
    There is also let which is similar to var in that it also gives a local scope, but it differs in that it receives block scope. It is not accessible outside of a for/if/while etc.
  • Sartheris Stormhammer
    Sartheris Stormhammer about 7 years
    that's why people must stop using 'var'
  • Mark Reed
    Mark Reed about 7 years
    Thanks for the reminder, @SartherisStormhammer. Updated to address the availability of let in the modern language.