Why can't I declare a variable inside a for loop? - javascript

Why can't I declare a variable inside a for loop below?
Wrong:
for(let i = 1; i <= num; i++){
let factorials = [];
if(num % i === 0){
factorials.push(i);
}
}
// ReferenceError: factorials is not defined
Correct:
let factorials = [];
for(let i = 1; i <= num; i++){
if(num % i === 0){
factorials.push(i);
}
}

If you define a variable inside of { }. It means that the variable is only alive inside of the { }. It's called a scope.
You have a scope using if/while/for/function...
In the following example, the factorials variable is alive only inside of one loop iteration of the for. Which means that you are recreating a factorials variable every time you loop.
for(let i = 1; i <= num; i++){
const factorials = [];
if(num % i === 0){
factorials.push(i);
}
}
If you want to make it work, you have to create your variable outside of the for so it will not be recreate after every iteration, and keep it's values.
const factorials = [];
for(let i = 1; i <= num; i++){
if(num % i === 0){
factorials.push(i);
}
}

In the first code snippet, you are declaring factorials inside the for loop block, hence it will not be visible outside the for loop block.
It is working in the 2nd snippet because you declared it outside of block.

Why can't I declare a variable inside a for loop below?
No, you can.
Here is the proof.
let num = 5;
for (let i = 1; i <= num; i++) {
let factorials = [];
if (num % i === 0) {
factorials.push(i);
}
}
let factorials = [];
for (let i = 1; i <= num; i++) {
if (num % i === 0) {
factorials.push(i);
}
}
console.log("No Error.")

Yes, you can, but if you declare the factorials-array in the loop it's only available in that closure. So consoling it out of the loop won't work.
Here's a very informative article about closures:
https://javascript.info/closure
The whole javascript.info-site is very interesting, I am studying it for now to strengthen my javascript basics and fill not known informations-holes, although I am into web developing since years. But it never hurts to get more knowledge, even if its the basics.
Also I would advice you to use "use strict;" from beginning when developing, it helps to keep your scripts more clean, disallowing sources of errors.

Related

For loop skipping variable declaration on subsequent iterations

Why doesn't "i" always equal zero? Do subsequent iterations of the loop skip the var declaration? I know that at the end of the first iteration i = 1 but when it goes through subsequently does the var declaration not reset i = 0?
When I run the function with args it all works but I just don't know why the var declaration doesn't reset if that makes any sense. It would make sense to me if the var "i" was declared outside of the loop.
function multiply(arr, n) {
var product = 1;
for (var i = 0; i < n; i++) {
product *= arr[i];
}
return product;
}
The first section of a for loop declaration is (for the most part) only run once, at the very beginning of the loop. Your code is equivalent to:
function multiply(arr, n) {
var product = 1;
var i = 0;
for (; i < n; i++) {
product *= arr[i];
}
return product;
}
Which is equivalent to:
function multiply(arr, n) {
var product = 1;
var i = 0;
while (true) {
// for loop body:
product *= arr[i];
// for loop declaration part:
i++;
if (!(i < n)) break;
}
return product;
}
So, i is only assigned 0 once, at the very beginning.
I qualified the above with for the most part because, when the behavior is somewhat stranger when a variable is declared with let, and let has block scope, not function scope - with let, every iteration creates a separate binding for the variable name. (but that's not worth worrying about in your case - it's only really something that needs to be considered when the for loop uses the variable asynchronously)

The for loop in this program isn't working as expected

It is supposed to print prime n numbers. The for loop will run from 2 to x which will iterate each time. if i == x then it means that the number was not divisible and so it should be printed as prime
var n;
var x = 2;
var i;
function prime(n) {
while (n) {
for (i = 2; i < x; i++) {
if (x % i == 0) {
break;
}
if (i == x) {
document.write(i + " ");
n--;
}
x++;
}
}
}
prime(10);
When you try to execute this code, this will never get into the for loop and goes into an infinite while loop. You have got:
i = 2; i < x;
The i will never be less than x. And it doesn't enter the for loop and comes out. And n will always be 10, that goes on into an infinite loop.
You need to use the modulus operator to check if a number is divisible by them.
Maybe change your approach a bit and try to find the first X prime number using just for loops.
var n;
var x = 2;
var i;
function prime(n) {
if (n <= 0) return;
var i, j, p_no = 0, res = [];
for (i = 2; ; i++) {
var ifPrime = true;
for (j = 2; ifPrime && j <= Math.sqrt(i); j++) {
if (i % j === 0) ifPrime = false;
}
if (ifPrime) {
res.push(i);
console.log(i + ' ');
p_no++;
if (p_no === n) return res.toString();
}
}
}
document.getElementById('prime').innerHTML = prime(10);
<p id="prime"></p>
What's happening when the code runs is what Praveen describes. I want to address how you got to your algorithm in the first place.
It looks like you're trying to print all primes less than a specific number n. You've jumbled different aspects of your algorithm together. Specifically, you've combined a loop that exists to find whether a number is prime with a loop over all numbers less than n.
The first thing you can do to help manage this complexity is to use methods. If you had a method isPrime(k) that returns true or false if a given number is prime, then your function's main loop looks much simpler, and separates the two problems from each other:
function prime(n) {
for (var i = n; i > 1; i--) {
if (isPrime(i)) {
document.write(i + " ");
}
}
}
Then you can focus on defining the isPrime method separately, without getting its parts confused with the main loop:
function isPrime(k) {
for (var i = 2; i < k; i++) {
if (k % i == 0) {
return false;
}
}
return true;
}
Methods are a fantastic way of keeping algorithms simpler by isolating their components. They're building blocks one can use to make more complex systems without having to keep track of the whole. It lets you make smaller changes, each encapsulated from other concerns, meaning you have less to keep in your mind while you're making those changes. The less you have to keep in your mind, the easier it is to spot mistakes.

Why is this function creating an infinite looop?

The first function determines if a number is prime. The second function is supposed to create an array with all prime numbers up to and including the max value, but it gives me an infinite loop for some reason.
function isPrime(num) {
for (i = 2; i < num; i++) {
if (num % i === 0) {
return false
}
}
if (num <= 1) {
return false;
}
return true;
}
function primes(max) {
var all = [];
for (i = 2; i <= max; i++) {
if (isPrime(i)) {
all.push(i);
}
}
}
primes(17);
Your i variable is global, so both functions use the same i. This means the first function changes it while the second one is looping.
As the first function will have set i to num-1 when it finishes, and num was the value of i before executing it, it effectively decrements i with one. And so i will get the same value in the next iteration of the loop in the second function, never getting forward.
Solve this by putting the var keyword in both functions.
for(var i=2; // ...etc)
The variable i in your two loops are global variables and they overwrite each other so the first loop never ends.
In ur code problem is with the scope of variable i, In prime no calculation, u can check upto the sqrt of no, if no is not divisible by any no upto its sqrt, then it will a prime no, Try this:
function isPrime(num) {
let k = Math.sqrt(num);
for (let i = 2; i <= k; i++) {
if (num % i === 0) {
return false
}
}
return true;
}
function primes(max) {
let all = [];
for (let i = 2; i <= max; i++) {
if (isPrime(i)) {
all.push(i);
}
}
console.log(all)
}
primes(17);
primes(25);

Javascript - for loop iterates only once?

I have a for loop but it gets executed once where it should execute two times.
The $appointments variable holds the returned data from an ajax call. When I console.log($appointments.length) I get two which is correct but the iteration happens only once and I can't figure out why.
for (var i = 0; i < $appointments.length; i+=1) {
var rangeStart_hour = $appointments[i].timerange.substring(0, 2);
var rangeStart_minutes = $appointments[i].timerange.substring(3, 5);
var rangeEnd_hour = $appointments[i].timerange.substring(11, 13);
var rangeEnd_minutes = $appointments[i].timerange.substring(14, 16);
var rangeS = rangeStart_hour + rangeStart_minutes;
var rangeE = rangeEnd_hour + rangeEnd_minutes;
var rangeStart = parseInt(rangeS);
var rangeEnd = parseInt(rangeE);
var range=0;
if(parseInt(rangeStart_hour) == 12){
if(parseInt(rangeStart_minutes) == 0){
range = rangeEnd - 0;
}else{
range = rangeEnd - (parseInt(rangeStart_minutes)+20);
}
}else{
if(parseInt(rangeStart_minutes) == 30 && parseInt(rangeEnd_minutes) == 0){
// if start time 1:30 ,end time 3:00
range = (rangeEnd - (rangeStart + 20)); // 300 - 150 = 150
}else if(parseInt(rangeStart_minutes) == 0 && parseInt(rangeEnd_minutes) == 30){
range = ((rangeEnd+20) - rangeStart);
}else{
range = rangeEnd - rangeStart;
}
}
console.log(range);
for(var i=1; i<(range/50); i++){
$("a[data-time='"+(rangeStart)+"']").addClass('time');
rangeStart += 50;
};
};
This structure seems like a bad idea:
for (var i = 0; i < $appointments.length; i += 1) {
//...
for (var i = 1; i < (range/50); i++){
//...
}
}
You probably want to use different variable names for your nested loop counters.
You reinitialize the variable i in the second for loop, if you change
for(var i=1; i<(range/50); i++){
$("a[data-time='"+(rangeStart)+"']").addClass('time');
rangeStart += 50;
};
to use a different variable, say j it should work fine.
In JavaScript, the scope of variable is function scope. It means that all variable declarations are hoisted to the top of the function.
So, in your case:
for (var i = 0; i < $appointments.length; i += 1) {
...
for (var i = 1; i < (range/50); i++){
...
};
};
equals with
var i; // two variables with the same name are hoisted as the same variable.
for (i = 0; i < $appointments.length; i += 1) {
...
for (i = 1; i < (range/50); i++){
...
};
};
So, at the end of the second loop, "i" will be greater than or equal to range/50. If this value is not less than $appointments.length, the first loop will terminate after the first round.
Important: JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java.
In your code the "i" variable used twice, So second time initialized value is Incrementing in first for loop. That's why, Condition failed in first for loop and loop is terminating. Change the variable name in second or first for loop then it will be working as you expected

How do I make a the console.log count from 1 to 32?

So I was thinking something like
number = 1;
maxnum = 32;
cat = true;
if (cat == true){
number + 1;
}
something along those lines, but I don't know how to implement that into making a constant changing line of number from 1 to 32; On the console.log.
maxnum = 32;
for(var i=0; i<maxnum; i++}{
console.log(i);
}
Use this:
var num = 1;
var maxnum = 32;
for(var i = num; i <= maxnum; i++){
console.log(i);
}
use the variable, i, in the for loop as a counter. Each round through the loop, 'i' will increment by one. CodeAcademy will give you some good practice and basic info on for loops. Eloquent Javascript is for more in depth study on the javascript language.
You can use a 'for' loop:
var maxnum = 32;
for (var i=1; i<maxnum; ++i) {
console.log(i);
}
You need to use a loop in your answer, either a for loop or a while loop.
If you change your if statement to a while loop, for example, and you can do this as follows.
number = 1;
maxnum = 32;
cat = true;
// Change "if" to "while" to make it a loop
while (cat == true){
// Add the following line to print:
console.log(number);
// Update the "cat" variable:
cat = (number < 32);
// Make sure this line uses assignment:
number += 1;
}
However, a for loop is a much cleaner solution. See the other answers posted here for examples of how to use a for loop.
var i = 1,
maxnum = 32;
while (i <= maxnum){
console.log(i++);
}

Categories