Why does console.log() keep on going in this loop? - javascript

I defined a variable 'i' to be equal to 2, and then say: if 'i' is between 0 and 2, let the function 'animate' run. However, if I open up the console in JSFiddle (option-command-I), the console.log() continues decreasing by 1 below 0! Am I using the conditional in the if statement improperly?
var interval = window.setInterval(animate, 500);
var i = 2;
if (0 < i < 2) {
function animate() {
alert('run');
i--;
console.log(i);
}
}
JSFiddle: http://jsfiddle.net/lpsternotes/RuLHn/

There are two problems here.
Firstly, there is this: 0<i<2. This will always evaluate to true.
Why? What you hoped it meant was "i is between 0 and 2" (which could be written as 0<i && i<2). But to a JS compiler, it is just two instances of the < operator. First, 0<i is evaluated, resulting in either true or false; then, that result is compared against <2 - so we have either true<2 or false<2. In order to answer that question, JS must "cast" the true or false to an integer. It treats false as 0, and true as 1; since these are both <2, the final result is always true.
Secondly, there is the position of your if statement, which is checked only once:
if (0 < i < 2) {
function animate() {
If you read through the code, you will see that there is no way of getting back to the line above this if statement, since the only repeating part of the code is the interval repeatedly running the animate function. To run each time the function runs, the if needs to be inside the function, not the other way around.

You need to clear interval once you satisfy the condition and move the if condition (note that 0 < i < 2 needs to be split into 2 conditions joined with && but here you can just do) with modification inside the function.
var interval = window.setInterval(animate, 500);
var i = 2;
function animate() {
if (i > 0) {
console.log('run');
i--;
console.log(i);
}
else{
window.clearInterval(interval);
}
}

Why don't you put if statement inside your animate function?
var i = 2;
function animate () {
if (i> 0 && i<2) {
alert('run');
i--;
console.log(i);
}
}
Edit:
1) you might want to use i>0 && i<2 rather than 0
2) Not sure if you do need to clear the interval after the condition is met. Would be better if you could elaborate a bit more about your requirements.

Related

while loop to print out only odd numbers in javascript

let number = 0;
while (true) {
if (number%2 === 0) continue;
console.log(number);
number ++;
}
I wanted to infinite loop to print out only odd numbers. But this doesn't seem to work. What am I doing wrong?
Let's have a brief understanding of the code execution.
When the following code is executed...:
let number = 0;
while (true) {
if (number%2 === 0) continue;
console.log(number);
number ++;
}
...the following happens:
The first line allocates memory for a variable named number and stores a value of 0.
The while loop starts, and it checks whether the condition is true, and yes it is, and always will be, as the condition is simply true.
Then, it checks whether the number mod 2 returns 0, and definitely, it does, since 0÷2 is 0 and the remainder is 0, so the condition inside the if statement is true, and therefore it executes the code correspondingly. When it sees continue, it jumps back to step 2 and checks the while loop condition, then comes back here, then goes back to step 2, then again comes back here and this never ends(ends when you stop the code execution or close your browser obviously).
Simply put, it never goes forward to the console.log and the number++ line. This is why your code isn't working.
The code from others work because the control actually moves forward in the code and never actually becomes stuck in the above loop.
Try this code
let number = 0;
while (true) {
if (number % 2 != 0)
console.log(number);
number ++;
}
The code you're using will not work because you defined number=0 and then you're checking the condition if(number%2==0) continue; so this condition will always return true because the number is defined 0 and the number++ will never increase.
let number = 0;
while (true){
if (++number % 2 == 1){
console.log(number);
}
}
no need a continue statement, just check the remainder is 1 the print the value in the loop.
you can further shorten the if condition as if (++number % 2)
You should increment the number when it is even also, to check the next number and so on:
let number = 0;
while (true) {
if (number%2 === 0){
number++;
continue;
}
console.log(number);
number ++;
}
Whatever number is, increment it first. Otherwise, when it is even, it never reaches to number++ any more.
let number = 0;
while (true) {
number ++;
if (number%2 === 0) continue;
console.log(number);
}

How to make a JavaScript 'while' loop more elegant?

I've made a JavaScript 'while' loop to keep adding a random number from 1 to 10 to an array until the random number is 9 or 10.
function random() {
return Math.floor(Math.random() * (10)) + 1;
}
var array = [];
var element = 0;
while (element < 9) {
element = random();
if (element < 9) {
array.push(element);
}
}
console.log(array);
I have two questions.
How can I make the 'while' loop more elegant - without using (element < 9) two times?
How can I do this in a more elegant way, without using a 'while' loop?
To answer your first question, you can initialise element with a random value to begin with:
var element = random();
while (element < 9) {
array.push(element);
element = random();
}
This gets rid of the inner if.
To answer your second question, it doesn't get more elegant than this really. If you really want to use something else, you could use a do-while by changing around your code but really it's the same thing.
An even better alternative (I credit #NiettheDarkAbsol) for this, is to perform the assignment and check in one step:
while ((var element = random()) < 9) {
array.push(element);
}
You eliminate the need to even declare it outside, or call random() in more than one place.

How to make an infinite for loop (for(;;)) not crash?

I'm new to JS, so most of my code hasn't worked. I've made a program to find out every prime number, but every time I use it, it crashes. Is there any way to make this code not crash upon running?
var i = 0;
for (;;) {
if (i % 2 === 0 || i % 3 === 0 || i % 5 === 0 || i % 7 === 0) {
i++;
}
else {
return i;
i++;
}
}
The correct approach is to use a single timer. Using setInterval, you can achieve what you want as follows:
window.onload = function start() {
primes();
}
function primes() {
var i = 0;
window.setInterval(function () {
if (i % 2 === 0 || i % 3 === 0 || i % 5 === 0 || i % 7 === 0) {
i++;
} else {
console.log(i);
i++;
}
}, 1000); // repeat forever, new value every 1 second
}
This will print the values to the console once a match is found (It does a check every second). But you can adjust this on the second parameter of the setInterval function.
If you want the results on the actual page, you can replace the console.log() with document.createTextNode().
Also, i have not checked this or know if the algorithm is right. Just adapted from your code.
List of fixes:
You manually update i and use a blank for loop instead of using the for loop normally, but having the middle condition always return true (a while loop could be used here also, but would still require manually updating i) as you don't plan on stopping. However, you can actually just put the whole thing in a timer instead of a loop, like #Leonel Atencio did.
You use return outside of a function, and if you did put this code inside of a function, it would just return the first prime number every time, so it would always return 1.
The formula is incorrect, only checking for some examples of primes; As #Alexandru-Ionut Mihai said, 121 would be considered prime, even though it is 11x11.
Fixed:
var primes = [];
var i = 1; //Start at 2; since "i" is incremented at the start of the function, this won't start it at 1, which would cause problems (the array would only have 1 in it, since all other whole numebrs are divisible by one)
setInterval(primeFunc,100);
function primeFunc(){
i++; //Increment current number
isPrime=true; //Assume prime
for(var j=0;j<primes.length;j++){ //Rule out non-primes with the power of modulo
if(i%primes[j]==0) { //If the current number can be divided (is divisible) by any previous prime...
//...then it's not a prime, so cancel any further chacks and move on
isPrime=false;
break;
}
}
if(isPrime){
//The current number is not divisible by any other primes, so it is itself a prime; if it was divisible, isPrime would be set to false by our loop above
primes.push(i);
output.innerHTML=primes;
}
}
<span id="output"></span>

JavaScript: setInterval and for loop explanation

i searched around for a couple of questions related to the use of the for loop and the setInterval function in JavaScript but i couldn´t find a concrete answer on why this snippet doesn´t work. Could someone explain please what´s happening under the hood and why this code doesn´t print anything at all?
for (let i = 0; i++; i < 10) {
window.setInterval(function () {
console.log('Test');
} , 100)
}
Your for loop is not correct. The condition needs to be the second statement in the for loop.
Following code should work.
for (let i = 0; i < 10 ; i++; ) {
window.setInterval(function () {
console.log('Test');
} , 100)
}
Expected Syntax for loop. You can read more here
for ([initialization]; [condition]; [final-expression])
statement
EDIT 1:
Though all answers (including mine) mentioned that condition needs to be second statement in the for loop which is correct. There is one more additional important behavior.
The for loop for (let i = 0; i++; i < 10) is actually correct in terms of grammar and even the javascript runtime executes this code.
But, as in your case, if the condition is evaluating to falsy value then it would exit the loop.
Breaking your for loop for (let i = 0; i++; i < 10) into each seperate construct
Initialization: let i = 0; This statement initializes the value of variable i to 0.
Condition: i++; Javascript evaluates the statement to check if the statement is true or not. In case of i++ the runtime firstly checks for the current value of i which is 0 . Since 0 is considered a falsy value the condition evaluates to false and hence the statement is not executed. Also, i++ statement is a post increment which basically increments i and then result the original value of i.
So, if you would have written loop like below, using the intiliaztion of i=1, then it would have worked, though it would be running infinitely untill the browser/Server crashes as the condition i++ would always evaluate to true. I hope that makes sense.
for (let i = 1; i++; i < 10) {
// Statements would run
}
Or
for (let i = 0; ++i; i < 10) { **// Pre increment**
// Statements would run
}
Or
for (let i = 0; i=i+1; i < 10) { **// increment i by assigment
// Statements would run
}
Douglas Crockford in his book Good Parts mention about the usage of ++ & -- and how it can confuse readers.
your for loop syntax is wrong, should be
for (let i = 0; i < 10; i++)
your setInterval code will run every 100 milliseconds for each iteration of the loop (so 10 times every 100 milliseconds)
Nothing to do with setInterval, you simply malformed your for loop:
This:
for (let i = 0; i++; i < 10)
Should be this:
for (let i = 0; i < 10; i++)
First declare the initial state of the loop, then the terminating state of the loop, then the incremental change of the loop.
Observe.

Recursive function to print numbers in JavaScript

I'm trying to make a recursive function to print 1 to 10 in JavaScript, my current code is:
function rec10(x)
{
if (x < 10)
{
$('#text').val(x+1);
x = x+1;
rec10(x);
}
}
The problem is, everytime I activate this function, the text box only shows "10" directly, i want the code to move from 0 to 1, to 2... until 10. Showing each one of them in the text box.
I tried to use setInterval and setTimeout but I didn't figure it out how to work with that. Thank you very much
instead of:
rec10(x);
call
setTimeout(function() { rec10(x); }, 1000);
With setInterval you can using code below:
function rec10(x) {
var interval = setInterval(function() {
if (x >= 10) clearInterval(interval);
$('#text').val(x++);
}, 1000);
}
JavaScript is single threaded, which means while your code runs, the changes you make to the DOM won't be seen on the browser until your code finish.
You need to give control to the browser for couple of seconds, it can be done with setTimeout:
function rec10(x){
if (x < 10){
$('#text').val(++x);
setTimeout(function(){
rec10(x);
},20);
}
}
Did you resort to setInterval/setTimeout only because you can't make a working recursive function?
If that's the case, how about this recursive function below without using setInterval/setTimeout:
function rec10(x) {
if (x <= 10) {
if (x <= 0) x = 1;
//append?
$('#text').val(x);
rec10(x + 1);
}
}
rec10(1);
But the problem with the code above is it will happen so fast you won't notice the printing of numbers 1 up to 9.
If you want to see the those numbers then I suggest you just append the value to your placeholder $('#text').
But if you really wanna see the numbers being printed and then being replaced by the next number, then you can refer to the answers posted by other users which uses setInterval/setTimeout.

Categories

Resources