formulation of do loop - javascript

I am completing a book called "DOM Scripting - Web Design with JavaScript and the Document Object Model" written by Jeremy Keith.
Here is the 'do...while' example given:
var count = 1;
do {
console.log(count);
count++;
} while (count < 11);
In the book he has stated that if we look at our do...while loop example we can be formulate it in full like this:
initialize;
while (condition) {
statements;
increment;
}
Surely this is in fact a mistake and this is actually the formulation of a while loop and not a do...while loop.
I have also checked the Errata to see if this was an error in the book but there is no mention of it.
Am I correct in saying this is the formulation of a while loop and not a do...while loop? Is there some authoritative ECMAScript documentation I can consult?

In the book that you mentioned above , do-while has been described like this :
As with the if statement, it is possible that the statements contained within the curly
braces of a while loop may never be executed. If the condition evaluates as false on the
first loop, then the code won’t be executed even once.
There are times when you will want the code contained within a loop to be executed at
least once. In this case, it’s best to use a do loop. This is the syntax for a do loop:
do {
statements;
} while (condition);
This is very similar to the syntax for a regular while loop, but with a subtle difference. Even
if the condition evaluates as false on the very first loop, the statements contained within
the curly braces will still be executed once.
So it becomes clear after reading this section that the author never says that do-while and while are the same. What he says is that, whatever you are doing using while, you can do the same using do-while. However, in a while, if condition evaluates to false during the first iteration itself, it will not even enter the loop. But in do-while, since iteration in the syntax is specified later, so it will enter the loop at least once. That's pretty much what he means.

Related

Doubts regarding a variable scope with declaration variable via let

I've run into the strange assertion in a book in my point of view. I guess that I don't understand something but anyway it will be great if you shed light on the situation.
ajax('<host1>/items',
items => {
for (let item of items) {
ajax(`<host2>/items/${item.getId()}/info`,
dataInfo => {
ajax(`<host3>/files/${dataInfo.files}`,
processFiles);
});
}
});
An author pay attention on :
There’s another hidden problem with this code. Can you guess what it is? It occurs when you mix a synchronous artifact like a for..of imperative block invoking asynchronous functions. Loops aren’t aware that there’s latency in those calls, so they’ll always march ahead no matter what, which can cause some really unpredictable and hard-to-diagnose bugs. In these situations, you can improve matters by creating closures around your asynchronous functions, managed by using forEach() instead of the loop.
Instead of it they offer the following:
ajax('/data',
items => {
items.forEach(item => {
// process each item
});
});
Frankly speaking I expected that if we use let for loop it means we create a closure for each iteration therefore I don't see any hidden problems there.
You are correct, if the author's comment is on that exact code snippet, they were mistaken.
Loops aren’t aware that there’s latency in those calls [...] you can improve matters by [...] using forEach()
That changes nothing, forEach() is equally unaware of async calls made inside its callback as a for loop is of async calls made in its body. forEach() will "always march ahead" the same way a for loop will.
With let you cannot encounter the issue that the author seems to be worried about, as each iteration of the loop has its own item just like when using items.forEach( item => { ... .
Even with var there is no issue with that code, since the variable item is not used inside the callback to the ajax request. You could produce the author's concern by using var and using item inside the callback, such as: console.log( item.getId() );.
Note: It is important to be aware that the callbacks will most likely run in a different (seemingly random) order than they were initiated in. If you aren't aware of that it can cause surprising bugs, but that also has nothing to do with using a loop vs. forEach.
The authors of that book seem to have no clue. There is no problem of for (let … of …) that .forEach(…) would fix.
They talk about
creating closures around your asynchronous functions, managed by using forEach() instead of the loop
but the closure is not created by the forEach callback function, the closure is the callback passed into the ajax function. It closes over the surrounding scope, and there is hardly any difference between the for block scope (when using let or const) and the function body scope (when using forEach).

Is it a browser bug that I can't use js labeled statements with an if?

Disclaimer: Yes, I know goto is bad, I'm interested here in the spec and implementations, not best practices.
I have this super simple javascript example of a labeled statement
let i = 0;
foo:
if(i < 5) {
console.log(i);
i +=1;
continue foo;
}
As far as I can tell for the spec for labelled statements and for statements this should work!
So am I reading the spec wrong or is there a bug somewhere?
Note that usage as shown on MDN with for statements works fine
From the specification for continue:
It is a Syntax Error if this production is not nested, directly or indirectly (but not crossing function boundaries), within an IterationStatement.
An IterationStatement is defined as a for loop or a case block. An if block is an IfStatement, not an IterationStatement, so you cannot use continue inside one.
The problem is that continue can only be used in a loop.
The continue statement terminates execution of the statements in the current iteration of the current or labeled loop, and continues execution of the loop with the next iteration.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue

Continue Statement Confusion

The continue statement in javascript doesn't really make sense to me, or am I over thinking this?
For example, let's say I am for inning inside an object:
for (i in JM) {
if (JM[i].event == 'StartLocation') {
continue;
}
}
If that if statement is true, it's going to technically hop over that iteration. Why do we use the word continue then? Wouldn't it make more sense to use the word break? But, break does the total opposite, it stops the loop, right? (Or maybe a statement called hop) would make sense. Never really thought of this until a couple minutes ago :P
Yes, break takes you out of the loop and places you at the line after the loop. continue takes you directly back to the start of the next iteration of the loop, skipping over any lines left in the loop.
for(i in JM)
{ // continue takes you directly here
if(JM[i].event=='StartLocation'){
continue;
}
// some other code
} // break takes you directly here
If you're only asking about the word choice, then there probably isn't a great answer to this question. Using continue does cause loop iteration to continue, just on the next iteration. Any keyword could have been chosen. The first person to specify a language with this behavior just chose the word "continue."
The continue keyword is similar to break, in that it influences the progress
of a loop. When continue is encountered in a loop body, control jumps
out of the body and continues with the loop’s next iteration.
Understand it like this:
for(i in JM){
if(JM[i].event=='StartLocation'){
continue;
}
/*This code won't executed if the if statement is true and instead will move to next iteration*/
var testCode = 3;// Dummy code
}
break will break the for loop(come out of for loop) but continue will skip the current iteration and will move to next iteration.
You will find the relevant docs Here.

Can labels with "continue" and "break" jump to other statements?

What the title says is my question. I'm new to JavaScript. I am wondering if I can use statements to jump to certain lines of code. I have looked here and here. They don't explicitly say this can be done, but I think there might be a way for it to be done.
The way I understand it now it that I can designate any block of code or statement to have a label. I can attach that label to a break or continue statement, and it will jump to that line of code. But it seems, from the W3 tutorial, I can only jump to the top of the block of code where the label is.
It seems pointless to allow a continue statement to have a label proceed it when it can only be used inside of a loop and anything it can do with a label can also be done with a break and a label. In this example there is a break statement used to go to the top of the statement block; is there any difference in using the continue vs break?
I realize this could be bad practice because of what is hisorically known as "spaghetti code," but I am a curious person.
continue ends the current iteration and jumps straight to the next iteration in the loop, so basically to the top of the code block in the loop, if there is a next iteration to do.
break ends the loop, so it jumps past it. No further iterations are performed.
So that's quite a big difference. What they have in common, is that they can have a label to indicate a specific statement. So if you have a nested for loop, you can continue or break the outer for loop if it has a label. That doesn't mean that you jump to the label, it just means that you apply the break or continue to the loop indicated by the label, instead of the inner-level loop which you are in at that moment. You still have to be inside that labeled statement, though. You cannot jump to another part of the program.
What you are asking for is basically a goto statement. For that, maybe you'd like to read this question: How can I use goto in Javascript?
A break foo; does not "go to the top of a statement block" - it is not a GOTO.
Rather, the name specified informs JavaScript of which loop to break from, which is sometimes (although perhaps rarely) useful for nested loops.
Consider this code which does terminate:
outer: while (true) {
inner: while (true) {
break outer; // goes from here -->
}
}
// <-- to here
And a [flawed] variation, which loops until forcibly terminated:
outer: while (true) {
inner: while (true) {
// break; or,
break inner; // goes from here -->
}
// <-- to here
}
On the other hand, continue merely skips the remaining code within the loop - the post actions are performed and the loop condition is re-evaluated. That is, continue does not unconditionally terminate the loop.

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

Categories