JavaScript loop variable scope

JavascriptVariablesFor LoopScope

Javascript Problem Overview


Just a quick question about the scoping of JavaScript variables.

Why does the alert() function print the value of i instead of returning undefined?

$(document).ready(function () {
    for(var i = 0; i < 10; i += 1){
    }
        
     alert("What is 'i'? " + i);
});

I'm fairly new to JS, and in nearly all other languages I've dabbled, a declaration in the scope of the for loop would contain the value to that said loop, but not in this case, why?

i.e. What is 'i'? 10' is printed.

Javascript Solutions


Solution 1 - Javascript

See the MDN for the "initialization parameters" of a for-loop:

> An expression (including assignment expressions) or variable declaration. Typically used to initialize a counter variable. This expression may optionally declare new variables with the var keyword. These variables are not local to the loop, i.e. they are in the same scope the for loop is in. The result of this expression is discarded.

Solution 2 - Javascript

JavaScript didn't have block scope until const and let were introduced, just var which is function scoped. Since the initialization of i is within one function, that variable is accessible anywhere else in that same function.

From MDN:

> Important: JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java.

Solution 3 - Javascript

The javascript folks are trying to fix this!

EcmaScript6 (aka EcmaScript 2015) is the latest version of javascript that was passed last summer and browsers are just starting to support its features.

One of those features is block-scope local variables with the "let" expression. As of right now (April 2016), most of the current versions of the major browsers support this except Safari. Few mobile browsers support this.

You can read more about it here (in particular, see the section "let-scoped variables in for loops"): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

You can check current browser support here (look for the row Bindings -> let): https://kangax.github.io/compat-table/es6/

Solution 4 - Javascript

Unlike other languages (for example: Java, C++, C), JavaScript doesn't support block scope. Once you declare a variable in a loop or in a function it's scope is within the function body if you do

for(i=0; i<arr.length; i++) {
    var j=0;
    // ...
}

here your i becomes a global variable and j become local to the function or script in which the loop is.

Solution 5 - Javascript

for(i=0; i<arr.length; i++) {
    var j=0;
    // ...
}

it is not correct to state that the above creates a global variable i. I believe you should always use var to declare variables (unless you are intentionally wanting a 'property' rather than a 'variable' -which is pretty unlikely in 99.99% of JS coding scenarios ...)

Omitting var when assigning an initial value to i isn't creating a local or even a global variable, it is creating a property i for the global object (which may seem/behave mostly like a global variable - but they have some subtle differences).

better would be:

var i;
for(i=0; i<arr.length; i++) {
    var j=0;
    // ...
}

now the loop is using a global variable i (or function local variable i, if this code appears in a function)

see more about this at what is function of the var keyword and variables vs. properties in Javascript

-- note, what is a little confusing is that you can re-declare a variable, for example in a second loop

for(var i=0; i<9; i++){
    document.write('i = ' + i + '<br>');
}


for(var i=0; i<9; i++){
    document.write('i = ' + i + '<br>');
}

this seems to be valid (no errors when I test). It seems that you CAN re-declare variables in JavaScript - but it probably isn't every a good idea, unless a special case - see this related question mentioning how [Google Analytics makes use of the 'safe' redeclaration of a variable] (https://stackoverflow.com/questions/6888506/redeclaring-a-javascript-variable)

there is some discussion about re-declaring variables in JS (and also loop variables like i) in this related SO question: declare variables inside or outside the loop

There is event a JavaScript pattern for single declaration of variables

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
QuestionBlackBoxView Question on Stackoverflow
Solution 1 - JavascriptinsertusernamehereView Answer on Stackoverflow
Solution 2 - Javascriptuser2718994View Answer on Stackoverflow
Solution 3 - JavascriptMatt CoarrView Answer on Stackoverflow
Solution 4 - JavascriptHitesh KumarView Answer on Stackoverflow
Solution 5 - JavascriptMatt SmithView Answer on Stackoverflow