Javascript - for loop iterates only once? - javascript

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

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)

How to get value of a variable?

I am trying to figure out a script that adds 1 each time it runs to a variable, then console logs the total amount of times.
for (let i = 1; i <= limitFizzBuzz; i++) {
// Count the FizzBuzzes
let amountOfFizzBuzzes;
amountOfFizzBuzzes = amountOfFizzBuzzes += 1;
console.log(amountOfFizzBuzzes);
}
When I tried to run this in a loop, I get:
What am I doing wrong here?
First, a simpler version of the first problem:
let num;
num += 1;
console.log(num);
num += 1 is a correct statement that adds 1 to the value of num and stores the result back in num.
console.log(num); is a correct statement that writes the value of num to the console.
But let num; doesn’t give a starting value for num. When a variable isn’t initialized to a value in JavaScript, it gets the value undefined. Doing math on undefined as if it were a number results in NaN, which is what you see.
So, a fixed version of the simpler code gives an initial value to num, like zero:
let num = 0;
num += 1;
console.log(num);
The next issue is scope. If you declare a variable inside the loop, it’s a new variable each time around. Instead, you want to use the same variable for every iteration, and have it keep its value, so move the declaration outside:
let amountOfFizzBuzzes = 0;
for (let i = 1; i <= limitFizzBuzz; i++) {
amountOfFizzBuzzes += 1;
console.log(amountOfFizzBuzzes);
}
first you Define a var let amountOfFizzBuzzes; inside a loop so that should be outside the loop
second if you need to increment a number this is a right way to do it
let amountOfFizzBuzzes=0;
for (let i = 1; i <=limitFizzBuzz; i++) {
// Count the FizzBuzzes
amountOfFizzBuzzes+= 1;
console.log(amountOfFizzBuzzes);
}
.
.
//....
limitFizzBuzz = 5;
//if you want to start from zero & increment it X times
let amountOfFizzBuzzes = 0;
for (let i = 1; i <= limitFizzBuzz; i++) {
// Count the FizzBuzzes
amountOfFizzBuzzes += 1;
console.log(amountOfFizzBuzzes);
}
#Morrison is absolutely correct.
Just initialize your amountOfFizzBuzzes above the for loop.
let amountOfFizzBuzzes =0;
for (let i = 1; i <= 10; i++) {
// Count the FizzBuzzes
amountOfFizzBuzzes++;
//amountOfFizzBuzzes +=1;
console.log(amountOfFizzBuzzes);
}

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

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.

first loop not working

My Inner loop seems to work fine, but once the inner loop is complete i expect the first loop to start again but it doesn't and it's not clear to me why...
if(search)
{
// loop through Revenue Arrangements
for (var x = 0; search != null && x < search.length; x++)
{
var revenue_arrangement = nlapiLoadRecord('revenuearrangement', search[x].getValue(columns[0]));
nlapiLogExecution('DEBUG', 'Revenue Arrangement Internal ID', search[x].getValue(columns[0]));
var count = revenue_arrangement.getLineItemCount('revenueelement');
for (var x = 1; x <= count; x++)
{
var rev_element_id = revenue_arrangement.getLineItemValue('revenueelement', 'transactionline', x);
if(rev_element_id)
{
nlapiLogExecution('DEBUG', 'Element Internal ID', rev_element_id);
}
}
nlapiLogExecution('DEBUG', 'End of Inner Loop);
}
}
your both loops (inner and outer) are using the same variable as counter (x)
Use different counter variables for both
if(search)
{
// loop through Revenue Arrangements
for (var x = 0; search != null && x < search.length; x++)
{
var revenue_arrangement = nlapiLoadRecord('revenuearrangement', search[x].getValue(columns[0]));
nlapiLogExecution('DEBUG', 'Revenue Arrangement Internal ID', search[x].getValue(columns[0]));
var count = revenue_arrangement.getLineItemCount('revenueelement');
for (var y = 1; y <= count; y++)
{
var rev_element_id = revenue_arrangement.getLineItemValue('revenueelement', 'transactionline', y);
if(rev_element_id)
{
nlapiLogExecution('DEBUG', 'Element Internal ID', rev_element_id);
}
}
nlapiLogExecution('DEBUG', 'End of Inner Loop);
}
}
You're reusing the x variable and the nested iteration affects the outer one. This was stated clearly in other answer, but let's extend this to point to two aspects of javascript you might be not aware of, but you should:
Javascript uses block operators {} but it does not implement block
scope. This means that a for loop does not create a new variable
scope. This is significant if you come from c/c++ background.
See more:
http://doctrina.org/JavaScript:Why-Understanding-Scope-And-Closures-Matter.html
(also see for closures, that is how outer scope affects nested function scopes).
Javascript hoists variable declarations to the beginning of a
function scope. This means both of var x are effectively declared
in the very beginning of the snippet included in the question (or
possibly even earlier).
See more:
http://www.w3schools.com/js/js_hoisting.asp
Extra var hoisting example which shows how bizzare can be its effects: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
The above means that your code (simplified) of this:
var search = ["a","b","c","d"], count;
if(true) {
for (var x = 0; x < search.length; x++){
count = 2;
for (var x = 1; x <= count; x++){
console.log("innner", x)
}
console.log("outer", x)
}
}
is the same as this:
var search = ["a","b","c","d"], count, x = 1;
if(true) {
for (; x < search.length; x++){
count = 2;
for (; x <= count; x++){
console.log("innner", x)
}
console.log("outer", x)
}
}
That means you don't only have two loops that affect each other. You're also ignoring the 0 element of the first array (the var x = 1 in nested loop overrides var x = 0 in the outer).
Both snippets will output:
innner 1
innner 2
outer 3

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