Is there a loop "start-over"? - javascript

There is continue; to stop the loop and move to the next loop
There is break; to stop the loop and move to the end of the loop
Isn't there some kind of start; that stop the loop and move to the beginning of the loop?
I know it is easy to achieve all of these three actions by just modifying the value of i, but I always try to look for already built-it functions.

Resetting the value of your loop variable to the initial value then calling continue is as close as you'll get.
For example:
for(var i=0; i<20; i++) {
if(somecondition) {
i=-1; continue;
}
}

No - there is no keyword or other way to do it automatically.
As you already mentioned you can just modify the loop condition variable(s) within your loop. Easy if it's a simple i counter, but of course you may have more initialisation to do than just a simple counter.
Or you can do something like the following:
restartLoop:
while (true) {
for (var i=0, j=100000, x="test"; i < 1000; i++, j--, x+= ".") {
if (/*some condition, want to restart the loop*/)
continue restartLoop;
}
break;
}
The continue restartLoop will jump back out to continue with the next iteration of the while loop, which then immediately starts the for loop from the beginning including all of the initialisation code. If the for exits normally the break statement after it will break out of the containing while loop.
I don't really recommend doing this in a general sense, but if your loop initialisation process was really complicated it could be worth it because then you wouldn't need to repeat it all inside the loop. If you needed to do even more initialisation than fits nicely in the for statement's initialisation expression you can easily put it just before the for loop inside the while and it will all be re-run...

If you want to avoid jumps or the equivalent of goto statements that many of us have been trained to avoid, you could use a local function for the loop and a test on the return value to see if you should just call it again:
function doItAll() {
// put state variables other than the actual loop control here
function doTheLoop() {
for(var i=0; i<20; i++) {
if (somecondition) {
return(true); // run the loop again
}
}
return(false); // done running the loop
}
while (doTheLoop()) {}
// do some things after the loop
}

No. (Just to rule out a "I just haven't heard of it, either" - it isn't mentioned at https://developer.mozilla.org/en/JavaScript/Reference/Statements.)

continue works by simply skipping the rest of the loop body. break works by skipping the rest of the loop body and then ending the loop. A start function would have to somehow "rewind" the state of the program - but not all of the state of the program, since presumably you don't want to lose what you did, either - to where it was when the loop began, which is not something that any programming language that I have seen provides.

You could have the loop in a function that calls itself recursively:
function loopIt(numTimes) {
if (numTimes < 3) {
for (x = 0; x < 20; x++) {
if (x == 5) {
loopIt(numTimes+1);
break;
}
}
}
}
You can obviously change the conditions to fit you logic as the above is a simple example.

Related

Exiting a for loop using a conditional

I had a problem which was that I was using a loop e.g
for(let i=0; i<10; i++){
if(i === 3){
// go to the next iteration of the loop
}
console.log(i)
}
and I was struggling to see how to get to the next iteration. I tried a "return" statement but this came up with the error "illegal return statement" and having done a quick search on the forums the answer was not obvious, so I thought I'd log it here so that next time I can find it easier.
Having looked through the MDN docs, what IU actually wanted was a "continue" statement which short-circuits the rest of the code in the block and goes straight to the next iteration.
You just have to write a continue keyword in for loop to goto next loop,
for(let i=0; i<10; i++){
if(i === 3){
continue;
}
console.log(i)
}
Note: choose let judiciously, it can also be used with var as it is having a function scope.
If you want to skip the rest of code in current iteration and get to next one, continue;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
If you want to exit loop completely, use break;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

Iterating a for loop outside of the initial conditions

For instance let's say I have the normal loop:
for(var i = 0; i < 25; i++)
{
//code executes here
}
Notice the i++ I know it iterates the loop however, I am wonder if I can iterate elsewhere in the loop. Like so:
for(var i = 0; i < 25)
{
//code executes here
i++;
}
I attempted to implement it but it did not work. Is it possible to do it in this way?
There has to be a third expression in the for loop header, but it doesn't have to do anything and can in fact be empty. All you need is the semicolon.
for(var i = 0; i < 25; )
{
//code executes here
i++; // increments "outside of initial conditions"
}
Note that the for loop construct exists in the form it does because that's a very common pattern, and sticking to it whenever possible is a good idea to avoid unpleasant mistakes. For example, it means that you have to be careful with continue statements in the body of the loop:
for (var i = 0; i < 25; ) {
// code ...
if (whatever)
continue;
// code ...
i++;
}
The continue statement in a for loop does evaluate the third header expression, but it will skip the expression inside the loop body.
You can use any combination of statements for C-style "for" loops.
Initializer
The first statement is the initializer. This can be blank.
for (var i = 0; ...) // initializing in loop
for (; ...) // initializing outside of loop
Break Condition
The next statement is the condition: this typically cannot be blank unless you have a break statement in the loop, otherwise the for loop will become infinite. This is the greatest difference between "for" loops and "while" loops, so don't omit it.
for (;;) {
break;
}
Incrementor
The final statement is the incrementor. This increments the value so the break condition can trigger. You can easily omit this as well, as long as all branches of the loop will increment the value.
for (var i = 0; i < 25;) {
i++; // here's our incrementor
}
Why C-Style Loops Have Conditions Inside the Loop
Decomposing the full C-style for loop into each of it's pieces does the following:
var i = 0;
for(;;) {
if(i < 25) {
// your normal code would go here
i++;
}
else {
break;
}
}
There are many good reasons this is condensed into a single block within the "for" loop: writing code like this is verbose, prone to bugs, and makes it easy to create infinite loops by accident (crashing your program or exhausting a CPU until the program is quit).
Why Your Example Fails
You need to explicitly state you have a blank statement with at least 2 semicolons (3 statements) inside the loop. Otherwise, the code cannot be interpreted. The following line only has 2 semicolons:
for(var i = 0; i < 25)
The correct line is the following:
for(var i = 0; i < 25;)
Abstracting
Decomposing for loops to either change the break condition or the incrementor is bad form. Don't do it. However, if you must, this is probably a case of wanting to use a "while" loop. Typically, you wish to turn all of your suitable "while" loops into "for" loops, but there are rare exceptions. Just be warned: this easily leads to infinite loops, using up resources until you end the interpretor. "For" loops protect you from this.
You might be interested in break and continue statements. They give you more control over your loop.
//test if prime
var testInt = 42
for(int i = -10; i < testInt; i++) {
if(i<2) continue;
if(testInt%i==0) break;
}
Just make sure that no continue is called without previously changing the value of your variable. Otherwise an infinite loop is created.
An infinite loop in javascript is very bad. It freezes the browers and debugger, which means it is nasty to debug.

FizzBuzz in Javascript: the code won't execute or print at all

Have been playing around with the FizzBuzz problem, and I am wondering why the following code won't execute, nothing gets printed to the console.
var i = 0;
while (i = 0, i < 100, i++ ) {
if ( i % 3 === 0) {
console.log("Fizz");
} else if ( i % 5 === 0) {
console.log("Buzz");
} else {
console.log(i);
}
}
What am I missing?
You used the wrong looping construct. It should be a for, not while. Also note that it's semicolons between the clauses, not commas:
for (i=0; i < 100; i++) {
What you have is this:
while (i = 0, i < 100, i++) {
The comma just evaluates the left side, throws the result away, and then evaluates the right side. So that sets i to 0 (and discards the zero value returned by the assignment), tests that i is less than 100 (but does nothing with the true value returned by the comparison), and uses the value of the last expression (i++) as the loop condition for the while. Since i is 0, which is falsy, the loop body never executes.
Note that if you had used ++i instead, it would make no difference in the for case, but your while version would loop forever instead of not running at all, since i would already have been incremented to 1 the first time it was tested for truthiness.
I believe you are simply confusing the way you make 'for' and 'while' loops. You've built your 'while' like you would a 'for'!
Think of it this way: when you write a while loop like this:
while(i<100) {
You're saying, while (this condition is true). All that you need between the parentheses is a statement to determine whether it's true or not. Somewhere in the loop, you (usually) would need to change the value of i, or you'd (probably) get an infinite loop.
Now, the for loop, we'll need more information between the parenthesis... we'll need all the information that determines the amount of loops we'll take. Just like you've written it there, we're writing for (when my variable equals this; Loop until this condition is true; change the variable like this).
Generally, this means that 'while' provides more flexibility in how you determine the logic of your loop, but a 'for' loop is probably the easiest to read.

javascript function won't loop

Here is a piece of a javascript practice problem that I am working on:
function combo(str){
var splitStr=str.split("");
for (var i=0; i<splitStr.length; i++){
return splitStr[i];
}
}
console.log(combo("dog"));
Why won't the loop return all three letters? It prints "d" and stops. If I take the loop out of the function, it works.
What am I doing wrong? Please explain.
return ends the invocation of the function, giving you back whatever is after that return
Your code structure looks like you wanted it to act like yield but ES5- does not support this so you can't use it (yet), and you would still have other problems (i.e. you'd be logging just the first generated result)
Instead, pass your console.log (bound to console) into a the loop;
function combo(str, callback){
var splitStr=str.split("");
for (var i=0; i<splitStr.length; i++){
callback(splitStr[i]);
}
}
combo('dog', console.log.bind(console));
With return you will end the function and come out of it with that data, next things wont be called
You can return an array instead like this.
function combo(str){
return splitStr=str.split("");
}
console.log(combo("dog"));
You are returning from inside the for loop and this ceases the function's execution. If you want to return each letter of the array, just return the split array itself:
function combo(str) {
return str.split("");
}
The behavior you seem to want is somehow achievable using generator function (function*).
function* combo(){
var splitStr = str.split("");
for (var i=0; i < splitStr.length; i++){
yield splitStr[i];
}
}
Then you'd invoke it like this:
var generator = combo("dog");
console.log(generator.next()) //d
console.log(generator.next()) //o
console.log(generator.next()) //g
Please note, however, that so far only few browser support this feature.
return stops the execution of the function. The rest of the loop is not happening.
'return' within the loop ends the loop and returns the first value, since it allowed the loop to run only once.
putting the 'return' statement outside of the scope {} of the loop will allow the loop to continue to run/repeat.

Does the ForEach loop allow using break and continue?

Does the ForEach loop allow us to use break and continue?
I've tried using both but I received an error:
Illegal break/continue statement
If it does allow, how do I use them?
No, it doesn't, because you pass a callback as a return, which is executed as an ordinary function.
Let me be clear:
var arr = [1,2,3];
arr.forEach(function(i) {
console.log(i);
});
// is like
var cb = function(i) {
console.log(i);
// would "break" here do anything?
// would "continue" here do anything?
// of course not.
}
for(var j = 0; j < arr.length; j++) {
cb(arr[j]);
}
All forEach does is call a real, actual function you give to it repeatedly, ignore how it exits, then calls it again on the next element.
In that callback function if you return it will incidentally work like continue in the case of forEach. Because the rest of the function won't execute that time, and it will be called again. There is no analogue of break.
Ruby supports this flexibility, using blocks/procs instead of methods/lambdas.
Per Mozilla's documentation:
Note : There is no way to stop or break a forEach loop. The solution is to use Array.every or Array.some. See example below.
every and some are exactly like forEach, except they pay attention to the return value of the callback. every will break on a falsey value and some will break on a truthy value, since they shortcircuit. They are exactly analogous to && and ||. && tests whether every expression is truthy, || tests for whether some is, which should help you remember how short-circuiting works with every and some. When in doubt, try it.
As already answered, you cannot use continue or break inside a JavaScript Array.prototype.forEach loop. However, there are other options:
Option 1
Use the jQuery .each() function (Reference).
Simply return true to continue, or return false to break the loop.
Option 2
Just use return to continue or throw new Error() to break. I don't necessarily recommend doing it this way, but it's interesting to know that this is possible.
try {
[1, 2, 3, 4].forEach(function(i) {
if (i === 2) {
return; // continue
}
if (i === 3) {
throw new Error(); // break
}
console.log(i);
});
}
catch (e) {
}
The expected result is just 1

Categories