Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - scope of nested for loop index

I remember variables are function scoped in Javascript. But, how is the behavior if I redefine the local variable in a loop. One common use case is nested loops. In the below code, if I change j to i, the outer for loop terminates after one iteration as the value of i in outer scope is same as inner for loop. Since I use var, I was expecting (similar to other language) it is redefined inside inner fo loop. Does this mean in JS, there is no way to redeclare and use local variable within function scope.

for (var i = 0, len = x.length; i < len; i++) {
            ...
            for (var j = 0, len = y.length; j < len; j++) {
                ...
            }
        }
like image 945
bsr Avatar asked Sep 25 '12 12:09

bsr


People also ask

What is nested scope in JavaScript?

Scopes can be nested. Inside an inner scope you can access the variables of an outer scope. The lexical scope consists of the outer function scopes determined statically. Any function, no matter the place where being executed, can access the variables of its lexical scope (this is the concept of closure).

DO FOR loops have scope?

The scoping semantics of the for loop dictate that after each execution of the loop, the object that was created during that iteration will be destroyed. Technically, the f is in a more inner scope than the i .

How does nested for loop work JavaScript?

The most common type of nested loops will be one loop inside another. The first loop is usually called the outer loop while the second loop is called the inner loop. The outer loop always executes first, and the inner loop executes inside the outer loop each time the outer loop executes once.

What kind of scope in does JavaScript use?

JavaScript has 3 types of scope: Block scope. Function scope. Global scope.


2 Answers

As you said, JavaScript only has function scope. Variable declarations are hoisted to the top of the scope in which they are declared. Your example is interpreted like this:

var i, j, len; //Declarations are hoisted...
for (i = 0, len = x.length; i < len; i++) { //Assignments happen in place
    for (j = 0, len = y.length; j < len; j++) {

    }
}

As for this part:

if I change j to i, the outer for loop terminates after one iteration

If you replace j with i, then after the first iteration of the inner loop, i will be y.length - 1, and the outer loop will either continue or stop, depending on the difference between x.length and y.length.

If you're interested in the real explanation of the internal workings, the ECMAScript spec (Declaration Binding Instantiation) covers it in detail. To summarise, every time control enters a new execution context, the following happens (a lot more than this happens, but this is part of it):

For each VariableDeclaration and VariableDeclarationNoIn d in code, in source text order do

  • Let dn be the Identifier in d.
  • Let varAlreadyDeclared be the result of calling env’s HasBinding concrete method passing dn as the argument.
  • If varAlreadyDeclared is false, then
    • Call env’s CreateMutableBinding concrete method passing dn and configurableBindings as the arguments.
    • Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.

This means that if you declare a variable more than once per execution context, it will effectively be ignored.

like image 187
James Allardice Avatar answered Sep 19 '22 08:09

James Allardice


Every var declarement will be put into the top of the current scope, so your code is same as:

   var i, j, len;
   for (i = 0, len = x.length; i < len; i++) {
        ...
        for (j = 0, len = y.length; j < len; j++) {
            ...
        }
    }

Check this: JavaScript Scoping and Hoisting

like image 45
xdazz Avatar answered Sep 23 '22 08:09

xdazz