Is there any reason to purposely introduce closures to prevent variable hoisting? - javascript

Consider this code:
for (var j = 0; j < 10; j++){
// ...
}
Assume that a for loop appears right after this one, which uses the same j counter variable. Netbeans complains that the second j redefines the first one, because of variable hoisting.
Is there any reason why or why not I should surround my loop with a closure:
(function(){
for (var j = 0; j < 10; j++){
// ...
}
})();
... to prevent the variable hoisting behavior, and stop Netbean's complaints?

Javascript variables have function scope - not the block scope you are probably used to. (This is a big Javascript wart that we must get used to)
The usual style rules suggest that it is better is to declare all variables, including loop variables just once in the beginning of the function. (Don't declare them inside the for statement - it makes sense in other languages but not in Javascript).
Hopefully this causes your compiler to calm down.
(You don't need to worry about both loops using the same variable that much - the variable is reinitialized anyway)

Is it complaining because you are redeclaring var? You can remove the second var since it would already be in scope.

The problem is that javascript variables are not block scoped but function scoped
Suppose you have a snippet like this
function MyDemo(){
var i = 0;
for( var j = 0; j < 10; j++ ){
++i;
}
alert( i );
alert( j );
}
In javascript j will be alerted as 10, while as in a block scoped language like C# or Java, it would be something like j not defined in the context
That being the problem, the solution is not to wrap it in a closure.
Why don't you use another variable or re-initialise the same variable without declaring again?
Useful Link: Explaining JavaScript Scope And Closures

Wrapping the loop in a closure seems unnecessary to me and could potentially cause issues if you're defining variables inside the for loop that you would like you use outside of the loop. For example:
(function() {
for (var j = 0; j < 10; j++) {
var foo = "bar"
}
});
// foo is undefined here
Whereas:
for (var j = 0; j < 10; j++) {
var foo = "bar"
}
// foo is defined here
From a micro-performance standpoint, the closure also creates unnecessary overhead since, as other people have said, if you take the var off of the second for loop, it should stop complaining.

99% of the time, the runtime performance hit of the extra function call is going to be irrelevant. What's more important is the extra code cluttering up your codebase and making things harder to read. I'd say don't wrap that in a function call just for your IDE's sake.

Related

Is it safe to access a for loop counter after the loop?

Is this ok?
for (var i = 0; i < 10; i++) {
...
}
doSomething(i);
Obviously I expect i to have the value 10 here. My testing indicates it's ok, but is this defined behaviour? (ES5)
Yes, this is defined behavior. The current version of JavaScript doesn't have block scoping, there is only function scope.
However, the new standard of JavaScript (ES6) is introducing a let statement (an alternative to var), which will respect block scope.
In the following code, you would not be able to access i outside of the loop:
for (let i = 0; i < 10; i++) {
...
}
This is really a question of scope. Do you want i to be accessible outside the for loop?
If so, and you want to make sure, define i outside the loop. Something like:
Duh... Variables in for loops aren't blocked (barring the let option in ES6). Which I already knew, but I'm tired and spaced it. So of course i will be accessible, and defining it outside the for loop is entirely unnecessary.
I'm going to leave this up as a reminder to myself not to jump the gun when I'm tired and haven't fully thought through my answer.
var i;
for(i = 0;i < 10; i++) {
...
}
doSomething(i);
Edit: After double-checking, i is definitely going to be accessible no matter what, and that is defined behavior, so it's safe either way.

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).

Declaring var inside Javascript for loop declaration

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).

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