13

I know that JavaScript vars point to a value:

var foo = true;
//... later 
foo = false;

So in that example I've changed foo pointing to true -> foo pointing to false, but if I do:

for (var i=0; i<100; i++){
    var someVar = i;
}

Am I creating a new var for each iteration?

Is there any difference in the following two ways of doing the same?

var myvar;
for (var i=0; i<100; i++){
    myvar = i;
}

and

for (var i=0; i<100; i++){
    var myvar = i;
}

If so, why?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
pjnovas
  • 1,086
  • 1
  • 8
  • 24

5 Answers5

15

There is no block scope in Javascript ES5 and earlier, only function scope. Furthermore, the declarations of all javascript variables declared within a function scope are automatically "hoisted" to the top of the function.

So, declaring a variable within a loop isn't doing anything different than declaring it at the top of the function and then referencing it within the loop.

See these two references for some useful explanation: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting and http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/.

Note: the assignment to a variable is not hoisted, just the declaration of the variable. So, if you do this:

function a() {
    for (var i=0; i<100; i++){
        var myvar = i;
    }
}

It works like this:

function a() {
    var myvar;
    for (var i=0; i<100; i++){
        myvar = i;
    }
}

If you wanted to create a new scope inside your for loop, you could use an IIFE (immediately invoked function expression) like this:

function a() {
    for (var i=0; i<100; i++){
        (function() {
            var myvar = i;
            // myvar is now a separate variable for each time through the for loop
        })();
    }
}

Update in 2015. ES6 (or sometimes called ES2015) offers the let declaration which does offer block scope. In that case a let variable declaration is hoisted only to the top of the current block scope. As of mid 2015, this is not yet widely implemented in browsers, but is coming soon and it is available in server-side environments like node.js or via transpilers.

So, in ES6 if you did this:

for (let i=0; i<100; i++){
    let someVar = i;
}

Both i and someVar would be local to the loop only.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
13

No, there is no difference; in JavaScript, variables are scoped on the function level, not the block level.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • 2
    While this answer, may seem overly simply. It is absolutely correct. And the point is honestly this simple. If you want to use Javascript productively you must understand function scope vs. block scope, +1 – Joe Oct 27 '11 at 03:13
  • 1
    The variable scope inside of the loop does not change on successive iterations. This answer and your support of it are not correct. There is a difference, although it is subtle and should not change the execution of any script. I've detailed it below. – Daniel Teichman Oct 27 '11 at 06:55
2

As @icktoofay said, in javascript there is no difference. In some languages, at each iteration, the variable will be instantiated, then go out of scope, and left to be garbage collected.

To simulate this in javascript, you could do:

for (var i=0; i<100; i++){
    (function(){
        var myvar = i;
    })();
}

In this case, myvar only exist in the scope of the anonymous function, so at each iteration, a new instance of myvar is created.

Ortiga
  • 8,455
  • 5
  • 42
  • 71
  • Uhhh, this doesn't actually execute anything. Nothing calls the inner function. Perhaps you meant to create an [IIFE (immediately invoked function expression)](http://stackoverflow.com/questions/23124067/what-are-good-use-cases-for-javascript-self-executing-anonymous-functions/23124112#23124112), but what you have here doesn't execute anything. – jfriend00 Jul 21 '15 at 21:02
  • @jfriend00 I wanted to represent the act of creating a variable in the scope of a function inside a for, so it's scope does not leak outside of the loop. How the function will be invoked is irrelevant and not included (although a named function would leak nevertheless). – Ortiga Jul 21 '15 at 21:11
  • I'm suggesting you improve your answer. It is absolutely relevant to doing anything useful as an uncalled anonymous function doesn't do anything. In fact, until it's called, it doesn't even create a new variable. – jfriend00 Jul 21 '15 at 21:14
2

Tools like JSLint recommend that you put all your var statements at the top of functions. It's because JavaScript essentially does it for you if you don't, so it's less confusing if you do. In your example, it doesn't matter where you put var as long as it occurs before one definition of myvar. Likewise, you may as well declare i at the top of the function as well.

What's more interesting is the hierarchical scope chain in which JavaScript searches for names when it wants to look one up. It searches up the scope chain from local to global until it finds the first instance of said name.

Which is why you can play games like this to annoy your friends:

function foofinder() {
    var bar = function () { return foo; },
        foo="beers";
    return bar();
}

foofinder();
>>> "beers"
kojiro
  • 74,557
  • 19
  • 143
  • 201
  • There is no "var statement". There is a variable declaration, which starts with the keyword *var*. The phrase `it doesn't matter where you put var as long as it occurs before one definition of myvar` doesn't make sense to me. Declarations are processed before any code is executed, so you can declare variables below where assignments are made to them (though it might be confuing to do so) and their scope will still be controlled by the declaration. – RobG Oct 27 '11 at 03:57
  • Several venerable resources refer to the use of `var` as a "`var` statement". One such resource is [JSLint](http://www.jslint.com/lint.html) (search for "var statement" on the page.) While the `var` keyword is indeed used for variable declaration, you can of course do a variable definition in the same expression for convenience. If you define and redefine a variable in the same scope, you can put the `var` keyword before any one of those definitions to the same effect. – kojiro Oct 27 '11 at 04:11
  • On checking, there is indeed a *VariableStatement* (ECMA-262 § 12.2) so I stand corrected. Your wording was unclear (to me), my attempt at correction made it worse. :-( – RobG Oct 27 '11 at 05:03
0

By constantly declaring var before the variable name, you could be instructing the JavaScript engine or interpreter to re-initialize the variable to an undefined value (undefined as opposed to a number, string/text, boolean value, or null) before assignment, which would be extra instructions, slowing down the speed of loop execution. You're also inflating code size and reducing the speed at which the code is parsed/interpreted/compiled.

For virtually any application, there is no functional difference, but there still is one and the difference might be noticeable after hundreds of thousands or billions of loop executions. However, repeated VAR declarations of the same name within a function leads to fatal exceptions in Chrome / V8.

UPDATE: Using var before the variable name is provably slower than omitting var as demonstrated by the following benchmark run on Chrome / v8 with the JavaScript console.

var startTime = new Date().getTime();
var myvar;
for (var i=0; i<100000; i++){
    myvar = i;
}
console.log(new Date().getTime() - startTime);

var startTimx = new Date().getTime();
var myvax;
for (var j=0; j<100000; j++){
var myvax = j;
}
console.log(new Date().getTime() - startTimx);
161
169

The first test executed in 161 ms and the second test (with var) took 169 ms to execute. That's a difference of 7 ms, consistent after multiple runs of the benchmark.

The entire benchmark was pasted into the Chrome JavaScript console and then compiled before its execution, which is why the first output does not appear below the first call to console.log().

Try it yourself!

Daniel Teichman
  • 590
  • 3
  • 10
  • Why is this answer down-voted? Isn't it obvious that declaring a variable over and over again in cycle is redundant? – katspaugh Oct 27 '11 at 11:04
  • 1
    I doubt any current JavaScript implementations reset the variable to undefined each time through the loop. Technically the variable is only declared once at the beginning of the function. – Matthew Crumley Oct 27 '11 at 13:55
  • @Matthew Crumley, well, `var x = 10; var x;` confirms your point. Is this the relevant part: http://code.google.com/p/v8/source/browse/trunk/src/ast.cc#90? – katspaugh Oct 27 '11 at 14:43
  • Daniel I have done that test below from @katspaugh comment and the var x is not initializing again, it still has 10 value. – pjnovas Oct 27 '11 at 18:22
  • 1
    I've read the spec, which hadn't occurred to me before, and it says: "If `varAlreadyDeclared` is false, then" (Ecma-262, 10.5), basically, declare it and set to `undefined`, and *no* `else`-clause. – katspaugh Oct 27 '11 at 18:52
  • Run it yourself. jsperf might not be accurate. – Daniel Teichman Oct 29 '11 at 00:53
  • @Daniel: I've run it with node.js after changing the number of iterations to 1,000,000,000 and there's consistently very little difference (~0-2ms) between the two. – icktoofay Oct 29 '11 at 02:26