"Var" or No "Var" in JavaScript's "For-In" Loop

var or no var in JavaScript's for-in loop?

Use var, it reduces the scope of the variable otherwise the variable looks up to the nearest closure searching for a var statement. If it cannot find a var then it is global (if you are in a strict mode, using strict, global variables throw an error). This can lead to problems like the following.

function f (){
for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

If you write var i in the for loop the alert shows 2.

JavaScript Scoping and Hoisting

Let vs. var in a for loop

This is a closure.

The function is defined inside the loop, so it has access to all the variables that exist inside the loop, and it closes over them and continues to have access to them so long as the function exists.

I am confused with javascript let and var in for loop?

When you use var:

var username = ['Sam', 'Adarsh', 'Rohit', 'Rajat'];
for(var i in username){
console.log(username[i]);
}
i // 3

When you use let

var username = ['Sam', 'Adarsh', 'Rohit', 'Rajat'];
for(let i in username){
console.log(username[i]);
}
i // Uncaught ReferenceError: i is not defined

let in ES6 will create block scope to function scope

Declaring var inside Javascript for loop declaration

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

Using var when declaring i in a for loop

Without a var declaration somewhere in a function, references to i will be to the i property of the global object. This risks all sorts of unpredictable behavior if code in the body of the for loop invokes code (say, inside a called method) that also modifies the global i.

Note that declaring var i in the for loop initialization

for (var i = ...)

is equivalent to declaring var i; before the for loop:

var i;
for (i = ...)

In particular, the declaration of i will be hoisted to the top of the enclosing scope.

EDIT: If you enable strict mode, then you must declare your loop variables (all variables, actually). Referencing a variable that has not been declared with a var statement will result in a ReferenceError being thrown (rather than resulting in a global variable coming into existence).

Is is possible to create a for-of loop without a variable?

No, you can't, not in the general case.¹ You can use the iterator² directly, though:

const hasAny = xs => !xs[Symbol.iterator]().next().done;

Or if you want to ensure you proactively release any resources the iterator holds (rather than waiting for them to be released automatically — think DB connection in a generator function or similar), proactively call return on it if it provides a return (not all do) like for-of does under the covers:

const hasAny = xs => {
const it = xs[Symbol.iterator]();
const result = !it.next().done;
if (it.return) it.return();
return result;
};

Live Example:

const hasAny = xs => !xs[Symbol.iterator]().next().done;
console.log(hasAny([])); // falseconsole.log(hasAny([1])); // true

Declaring variables inside or outside in a for-in loop

Those two snippets of code do exactly the same thing (and that's the case in most language such as C, C++ and C# amongst others). If the variable was redeclared at every iteration, then following your logic, it would also be re-initialized, and would constantly loop over the same object. Your loop would be infinite.

On a side-note, in JavaScript, all variable declarations get pushed to the function scope; this means that you can declare variables anywhere within a function, even within nested loops, and they will only be declared once.

Link to the var documentation

Relevant SO question

Other relevant SO answer

Edit courtesy of @torazaburo:

If you want to declare a variable with a local scope (as in, a variable that will only be defined in the current block such as a for, while or if, you can use the let statement:

let var1 = 123;

It also allows you to override variables with the same name but declared in a higher scope, such as in this example from the docs:

function letTest() {
let x = 1;
if (true) {
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}

See the full documentation (and examples) here.

Javascript variable declaration within loop

Because of variable hoisting in Javascript, there is no technical difference in execution between the var being at the top of the function or inside the for loop. If that is all you care about, then you can do it either way.

Just to refresh memory, Javascript hoisting means that code like your second code block is parsed and then execute just like your first code block. All var declarations within a function are automatically moved to the top of the function scope before execution. Assignments to those variables are kept where they are located in the code - just the declaration of the variable is moved.

So, the difference is more about how you want to code to look. When you put the var definitions inside the for loop, it makes the code look like the variables are being created anew for each iteration of the for loop, even though that is not the case. They are being assigned a value each iteration of the loop, but a new variable is not created. That would be the case if you used let instead of var since let has a block scope whereas var only has function scope.

In general, it is a good practice to only put code inside a loop that actually needs to be inside the loop. While it doesn't actually change anything in the execution whether the var is inside or outside the loop, it is just part of a good practice whereas other code being inside or outside the loop could make a difference.

In your case, I think this would be a better practice:

function abc(){
var liTags = document.getElementsByTagName('LI');
var divTags = document.getElementsByTagName('DIV');
var len = Math.min(liTags.length, divTags.length);
var a,b;

for(var i = 0; i < len; i++){
a = liTags[i].width;
b = divTags[i].width;

// now do something with a and b

}

return;
}

Here, you've removed the two calls to document.getElementsByTagName() from the loop which will make a HUGE performance difference.


Update in 2017. Javascript version ES6, now supports both const and let for declaring variables. They are block scoped, not function scoped like var, so if you declare one of them inside a for loop block, then there will be a new and separate variable created for each invocation of the for loop. While that wouldn't make any significant execution difference in the type of code you showed, it can make a difference if you had asynchronous code inside the loop that references the variable you were declaring. In the case of const or let used within the loop body, each asynchronous call would get its own separate copy of the variable which can sometimes be very handy.

  for(var i = 0; i < len; i++){
let a = liTags[i].width;
let b = divTags[i].width;

$.get(someUrl).then(function(data) {
// each call to $.get() here in the loop has it's own a and b
// variables to use here, which would not be the case with var
});

}

Variable not visible inside for loop

The variable

row[loopvariable]

is not initialized. You could use a default value and take an array with a guard operator (logical OR ||).

row[loopvariable] = row[loopvariable] || [];

A shorter approach could be just to push a new array to row, without using an aditional variable loopvariable

let row = [];
for (var key in supplies.food) {
row.push([key, supplies.food[key]]);
}


Related Topics



Leave a reply



Submit