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.
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.
'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.
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.
First of all you are correct in all your assertions.
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.
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).
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.
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 :)
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With