Declaring var inside Javascript for loop declaration - javascript

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?

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);
}

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.

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
}

Those are both exactly the same thing.

The two code block are identical. The first statement of the for loop is executed before the for loop starts, the loop is running while the second statement is true, and the third statement is run every time the loop iterates once.
This means that
for(var i = 0; i < 8; i++) {
//some Code
}
is identical to
var i = 0;
for(;i < 8;) {
//some Code
i++;
}
(The semicolon following the ( is to tell the computer that i < 8 is actually the second statement, not the first).

Related

JavaScript let and var usage

A while ago, I read some article about using let and var in JavaScript and they're saying that a variable you declare using "var" keyword (even in for loop) works only within it's function, so why is it possible to make multiple for loops in one function, each of them look like : for (var i = 0; i < array.length; i++);
and JavaScript has no problem with "redeclaring" the i variable? Thanks :)
JS has a special case for var as it allows hoisting, which means multiple declaration of the same variables is allowed and they got moved to the enclosing functional scope. However they are still the same variable. Consider the following code:
function foo(){
for(var i=0; i<3; i++){
console.log("x");
}
for(var i;i<6;i++){
console.log("y");
}
}
foo()
Notice there is no initialization of i in the second loop, but it will execute fine and produce 3 x and 3 y. It used to be a problem with old browsers, but new browser simply allows it with no error given.
A seemingly small question with a complex answer. var is the old method declaration. You can declare it anywhere and as many times as you want. JavaScript will not care. All declared variables are available immediately, because declaration gets moved up to the very beginning of the function's code. This is known as hoisting.
let is the new way of declaring variables. const exists, but we're not interested in that right now. let is block scoped. The rules behind let and scoping can be confusing, but it's advantageous to learn/understand. It is the future of JavaScript. I thoroughly talk about it in my blog post, here.
let gives you the privilege to declare variables that are limited in scope to the block, statement of expression unlike var.
var is rather a keyword which defines a variable globally regardless of block scope.
ES6 introduced the 'let' keyword to tackle this issue only. It allows a variable to be bound to its scope within a function so that you cannot re-declare it outside preventing hoisting issues. Example -
for(var i=0; i<5; i++) {
console.log(i);
}
console.log(i);
Here the output will be - 0 1 2 3 4 5
Instead of 5 we must get 'Uncaught Reference Error' since variable i should be accessible only within the function. Because of Hoisting in JavaScript, all the variables and function names are stored to one place before execution. So the code actually looks like the following -
var i;
for(i=0; i<5; i++) {
console.log(i);
}
console.log(i);
This is resolved if you use the let keyword.

Is this how `hoisting` work in JS? [duplicate]

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:
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.
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 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"
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.
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!

Counter mysteriously increments in loop

I have a simple loop which passes some data from a list through other functions, but when those functions return, the counter has mysteriously incremented:
for (i = 0; i < list.length; i++) {
alert(i) // ONE
doWhatever(list[i]);
alert(i) // TWO
}
doWhatever() looks like this:
function doWhatever (obj) {
for (i in obj) createThing(obj[i]);
}
How is it possible for the value of i in the original loop to change this way?
You seem to forget the var keyword.
Look at your code. And every where you have
for (i = 0; ...
change it to
for (var i = 0; ...
Because all the loops written without the var keyword change the same i variable (well, more precisely a loop written as such change the i of the enclosing scope having defined it, which is often the global one, especially if you never properly defined i).

Does it help to declare a variable (var i=0) outside of for loop? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript variables declare outside or inside loop?
So..I've seen many articles saying that we should use the following style.
var i;
for(i=0;i <= 10; i++) {
// do something here
}
I've been using the above style for while, but I just wonder if it really helps except the readability.
Isn't it same as the following?
for(var i=0; i<=10; i++) {
}
It makes a difference if for some reason (should never be the case) you've declared a global variable by the same name outside the context of the function.
http://jsfiddle.net/bFRKU/
var i = 'global';
function test(){
alert(i);
for(var i = 0; i < 10; i++){
//do something
}
}
test();
In the above example, you'll notice that the alert returns "undefined." This is because variable definitions are hoisted to the top of the function (no matter where they are declared within the function). So in reality, the above is interpreted as:
http://jsfiddle.net/bFRKU/1/
var i = 'global';
function test(){
var i;
alert(i);
for(i = 0; i < 10; i++){
//do something
}
}
test();
Thus the alert "undefined." Ultimately, the only reason to place your variable declarations at the top of your functions is to reduce this potential confusion.
​
No significant differences between the two -- purely a matter of opinion.
it's the same
It's done because in JS, the practice is to ensure that vars are declared in one spot, at the top of your function. Expressly because there is no block-scoping, and because of potential scope-chain resolution errors.
The error wouldn't come from declaring var, but rather, forgetting to, and relying on block-scope to have your back (which it doesn't, because it doesn't exist).

How do JavaScript variables work?

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:
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.
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 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"
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.
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!

Categories