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?
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:
It works like this:
If you wanted to create a new scope inside your
for
loop, you could use an IIFE (immediately invoked function expression) like this:Update in 2015. ES6 (or sometimes called ES2015) offers the
let
declaration which does offer block scope. In that case alet
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:
Both
i
andsomeVar
would be local to the loop only.No, there is no difference; in JavaScript, variables are scoped on the function level, not the block level.
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 putvar
as long as it occurs before one definition ofmyvar
. Likewise, you may as well declarei
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:
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:
In this case, myvar only exist in the scope of the anonymous function, so at each iteration, a new instance of myvar is created.
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, ornull
) 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.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!