Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding JavaScript for-loop better

While reading code from a JS Editor (Tern), I have come across various uses for the for-loop as seen in the snippets below:

code snippet 1 @ lines 463-468:

for (;;) {
  /* some code */
}

code snippet 2 @ lines 97-100

for (var i = 0; ; ++i) {
  /* some code */
}

On the same note, I also have come across a for-loop with an empty body e.g:

for (var p; p; p = someValue) /* empty body */ ;

I am trying to understand what happens in code execution flow.

My take is that for code in snippet 1, the for loop has no conditions, so it may continue endlessly? For code in snippet 2, i is continually incremented without a limit? For the third one, the loop continues till p is assigned something that evaluates to false?

These are the ideas I have in my mind yet I am not sure. Please assist.

like image 213
gmajivu Avatar asked Aug 05 '13 13:08

gmajivu


People also ask

Which is more efficient for loop or while loop in JavaScript?

For readability I would go with the 'for' loop, but that's a personal preference. You can try it yourself at jsperf.com/for-vs-while-loop-iterating. It's not a matter of efficiency, it's a matter of preference and readability. There's no practical difference as @pimvdb's test shows.

Is the for loop outdated?

'For' loops are considered obsolete, hence we should avoid using them. In single threaded languages like JavaScript, the 'for' loop acts as a thread blocker, which hinders the scalability of a system.

Why for loop is better than while?

For loops (at least considering C99) are superior to while loops because they limit the scope of the incremented variable(s). Do while loops are useful when the condition is dependant on some inputs. They are the most seldom used of the three loop types.


2 Answers

In Short

First of all you are correct in all your assertions.

  • The first loop runs until it is exited from abruptly (with a break, return, throw etc..).
  • The second loop runs until it is exited from abruptly but also performs a variable assignment, and increments a value.
  • The third for loop runs like a normal for loop until the center condition is falsey. Its body is empty.

But Why does JavaScript do this?

Let's dig into why this happens.

If we take a closer look at the language specification we can see that the following happens in a for loop:

IterationStatement : for ( ExpressionNoIn(opt) ; Expression(opt) ; Expression(opt)) Statement

I will treat these statements and that definition for the rest of the answer.

Now let's go through the cases.

In case one of for(;;) the following happens:

  • ExpressionNoIn is not present, so nothing is called for that clause (As clause 1 states).

  • The second expression is not in, so we do not return calls (as clause 3 states).

  • The third expression is empty so no "incremenetion" is performed (as clause 3.f states).

So it would basically repeat endlessly just as you predicted (until broken from with a break or returned from, or thrown from and generally anything that causes abrupt completion). (As clauses e and d tell us).

In the second case for (var i = 0; ; ++i) the following happens:

  • ExpressionNoIn is present, so we evaluate it, and assign it with get value (as clause 1 states). We do not assign it.

  • Then we repeat endlessly since the second expression is not here. So we continue until abrubt execution happens or a break happens. More specifically this is defined here.

  • We increment i on every iteration as clause f states.

In the third case for (var p; p; p = someValue) /* empty body */ ; the following happens:

This evaluates as a for loop. Statement is empty indeed but the for loop does not really care. The only difference is that no value is returned from the for loop. Basically it's a full and legal for loop. ; is simply an empty statement. It is useful when you want to run a for loop with no content in the actual loop. You see this sometimes in feature detection. This is also useful when you want to find the minimum n such that... .

You are correct in that it runs until the value is falsey, or more accurately calling ToBoolean on it produces false. As clause 3.a.ii specifies.

As you can see, this is all in the spec and well defined :)


Why do coders do this?

In the first snippet the perform their flow control with a break clause. if (eol >= pos || eol < 0) break; (they check for the end of line, and this could be done in a more conventional for loop).

In the second snippet again they do flow control using break:

 if (!definitions.hasOwnProperty(uniq)) { name = uniq; break; }

They again put it in a break statement inside the for loop.

The third snippet is out of context, but let's say we want to (trivial example) find the first number bigger than 10 (or the 10th div element, or occurance of a string - you get the idea). We could do :

for(var i=0;i<=10;i++);

And get the first number bigger than 10.

like image 95
Benjamin Gruenbaum Avatar answered Oct 20 '22 00:10

Benjamin Gruenbaum


You are correct in your understanding.

The first snippet is an infinite loop; there is no termination condition, so the loop will (in itself) continue forever. This is almost certainly accompanied by a break statement somewhere within the body, which will exit the loop when it is run. (The other option is that a thrown exception exits the loop, although it is bad practice to use exceptions as control flow.) This pattern (or an equivalent while (true) {...} ) usually occurs when the exit condition is too complex to express within the loop statement.

The second snippet is similar to the first, in that without a termination condition it will run forever. This will also require a break statement (or exception) to terminate the loop. The only difference here is that a counter variable is also being incremented on each iteration.

The third snippet is a loop with no body, though the test and variable update happen on each iteration of the loop. As you expected, this continues until p evaluates to false. This for loop is exactly equivalent to the while loop version:

var p;
while (p) {
    p = someValue;
}

which perhaps makes it clearer that the assignment happens repeatedly until !p.

like image 39
Andrzej Doyle Avatar answered Oct 19 '22 23:10

Andrzej Doyle