JavaScript For Loop Breaking Early - javascript

Why would a for loop terminate early in JavaScript? For some reason my outer for loop terminates after the first repetition. I am new to JavaScript but would expect something like this to work in Java.
function check(){
var elements = document.getElementById('fields').children;
var filteredMolecules = molecules;
console.log(elements.length);
for (i = 0; i < elements.length; i++) {
console.log(elements[i].id)
filterMolecules(filteredMolecules, elements[i].id, 0, 10);
}
}
function filterMolecules(molecules, parameter, lower, upper){
console.log('filtering');
var filteredMolecules = [];
for (i=0;i<molecules.length;i++){
var value = molecules[i].val()[parameter];
filteredMolecules.push(molecules[i]);
}
molecules=filteredMolecules;
}
In check(), I loop through elements which contains 22 items as shown by the first console.log(elements.length). If I remove the method filterMolecules(...) then all 22 IDs are logged. However, with the code as is, only the first id is logged.
I believe the filterMolecules method which should run elements.length number of times is causing the outer for loop to not work. Could someone please explain why this is happening. If relevant, in filterMolecules(...) the data is retrieved from Google Firebase with molecules[i].val()[parameter]. Additionally, both methods use the global variable molecules (line 3 and line 14)

When you don't declare variables in javascript you end up using globals (which can be a difficult to spot source of bugs). So here you are using the same global variable i for both loops. When you start looping thought molecules you are accidentally incrementing the counter loop of your first for. Use different variables or define them with :
for (let i=0;i<molecules.length;i++)
Which will give each loop its own version of i.
In this case, since the declarations are inside individual functions, you could use var too:
for (var i=0;i<molecules.length;i++) {
// etc.
}

Related

calling a function in for loop giving infinite loop but same works fine in while loop

So i was working on a function which takes anything as argument and console logs it inside a box or a cell. This is what i came up with:
var horiz='━';
var vert='┃';
var ulcor='┏';
var urcor='┓';
var blcor='┗';
var brcor='┛';
//create a cell/box
var cell=(d='')=>{
let h='';
if(d==undefined||d==null){
throw('cell needs an argument');
}
len=d.toString().length;
for(i=0;i<3;i++){
if(i==0){
for(j=0;j<len;j++){
h+=horiz;
}
if(i==0) console.log(ulcor+h+urcor);
}
if(i==1){
console.log(`${vert}${d}${vert}`);
}
if(i==2){
console.log(blcor+h+brcor);
}
}
}
Now when i was testing this i did following
cell('index');
cell(1);
gave following output:
┏━━━━━┓
┃index┃
┗━━━━━┛
┏━┓
┃1┃
┗━┛
and did other testing as well and it worked pretty well until i did the following test:
for(i=0;i<5;i++){
cell(i)
}
Above code should give me cells/boxes with 1,2,3,4 but instead this gave me an infinite loop and what i noticed is that its only printing cells with 4 (not 1,2 or 3) but infinite times.
And now here is the fun part. When I do following:
n=1;
while(n<10){
cell(n);
n+=1;
}
above code gives desired result and works fine.
Weird!! just Couldn't figure out why its running infinite times when i used it in the for loop but while loop works good. If any sort of improvement required in the code then please do mention it:)
When you declare a variable without the var, let, or const keywords, that variable is an implicit global. In your cell function, you use for(i=0;i<3;i++) where i is declared without a keyword.
Your calling for loop for(i=0;i<5;i++){ cell(i) } also uses i without a keyword which makes i refer to the same global variable. So your call function is actually manipulating i from within the function which makes the for loop behave in the unintended manner. The while loop uses a different variable, n, which is why it doesn't have the same problem.
Try changing the for loop inside call to for(let i = 0; i < 3; i++) to limit the scope of i. And, in general, use let and const to declare ALL variables, even (and especially) the ones in for loops.

Array reloop to remove previous set of array data generated

My file works just fine in the first round of loop when i try to rerun the function again. It shows the previous value of the previous loop when i try to use the value to match and after which it shows the correct value. If i run the function again and again, it keeps holding on to the value of the previous generated random value.
for (var i=0; i<9; i++)
{
var ranD = Math.floor(Math.random()*33);
if (mathStar.indexOf(ranD)== -1) {
mathStar.push(ranD);
item[i].innerHTML = mathStar[i];
}
else {
i--;
}
itemVal[i].value = mathStar[i];
}
Substitute using const and let for var within for loop to avoid creating global variables and --i could have unexpected results within the code where i++ is also used in the foor loop.
Is this the first occurrence of "mathStar"?
If this is the first place you're using mathStar, it means it gets created globally and that usually leads to confusion. In this case, take a look at this.
Looking at just this, it seems that you are not resetting your "mathStar" value. This way, any time you run this loop for the nth time, the values you have added to "mathStar" using mathStar.push(...) also occur in the list of values.

Beginner query: Using function parameters with a for loop, skipping the loop for some reason

I imagine this is something pretty simple but I'm stumped and think this could be a good learning moment for me.
Here's the code:
var sumAll = function(lowRange, highRange) {
var sumOf;
var i;
for (i = lowRange; i > highRange; i++) {
sumOf += i;
}
return sumOf;
}
module.exports = sumAll
I'm working my way through the odin project, currently doing TDD section. So the function skeleton and final line of code was premade. The function parameters in this case are 1, 4. Expected result of 10.
Instead my test is throwing back undefined. I checked and this changes depending on what I define it as at the top.
It is as if it's skipping the loop all together, I've no idea why this would be.
A for loop's 3 major pieces can typically be understood like this.
Initialize the variable
Continue looping for as long as the condition is true
Change the variable's value after every iteration
During step two of the list above, your code is running i > highrange. This will immediately test false and skip your loop, because i has a value of lowrange, and I assume lowrange > highrange will never be true. What you want in its place is i <= highrange, "less than or equal to."
For loops are tricky, these little mistakes will follow you even into advanced territories. :o
Your for loop never executes because you set i equal to lowRange and the execute condition is i > highRange. I assume lowRange < highRange so it terminates without entering the loop, since it will run while i is greater than highRange, but it never is.
initialize your accumulator
var sumOf = 0;
and change your loop condition
for (i = lowRange; i <= highRange; i++) {

JS For Loop Stopping Early after Calling Function

I have a Javascript Array that holds the contents of a page. In order to draw all the objects in the right places when the page loads I loop over the array and pull out the elements. This worked very well until I allowed the objects to have children within them.
The current array structure is
0-> {elements=[] frame={I keep the frame attributes here with key value pairs}}, 1-> {elements=[] frame={}}
However, I just started adding sub-elements to the elements array in each object. So now I have to loop through/draw each element, check to see if there are any children and if so then I have to draw them too.
The problem I'm having is that after I loop through the first 0 object and it's children the for loop stops running. Is it because I'm calling the same function multiple times? I've done that before so I don't think that's what is happening.
this.run_loop = function (spawn, dom) {
console.log(spawn)
alert(spawn.length)
for (i = 0; i < spawn.length; i++) {
console.log(spawn[i])
//alert("i one")
var newdom = dom + "_" + i;
this.synthesize_elements(spawn[i], dom, newdom)
if (spawn[i].hasOwnProperty('elements')) {
//alert("FOUND")
var newarray = spawn[i]['elements'];
if (newarray.length > 0) {
this.run_loop(newarray, newdom)
}
}
}
}
This is a little old but I encountered a similar issue and found my way here, but I figured it out and thought I'd post the solution if anyone else came across this. The issue in my case (and it looks like in your case as well though I can't be sure) was in the declaration of the for loop:
for (i = 0; i < spawn.length; i++)
You're not declaring that i is a new var. so if anything inside the
this.run_loop(newarray, newdom)
function also manipulates a counter variable called i that isn't declared a new var, it will also change the one in your outer scope, and kick you out of the loop if it goes over the length of spawn
just always declare:
for (var i; i< spawn.length; i++)
in your loops or make sure your counters are unique.

Javascript: TypeError variable is undefined

I am currently building a small web application with similar functionality across all modules. I want to code small generic functions so that all programmers next to me, call these functions and these functions return necessary but important data for them to implement their functionality. In this example, I am trying to deal with the typical "choose true or false" exercise. So from the template.php they call this function:
function checkAnswers(){
var radiobuttons = document.form1.exer1;
var correctAnswers = answers(); //this is an array of string
var checkedAnswers = checkExerciseRB(radiobuttons, 2, correctAnswers);
for(i=0; i<checkedAnswers.length; i++){
alert(checkedAnswers[i]);
}
}
Function checkExerciseRB is my generic function, it is called from checkAnswers.
function checkExerciseRB(rbuttons, opciones, correct){
var answers = new Array();
var control = 0;
for(i=0; i<rbuttons.length; i++){
var noPick="true";
for(j=0; j<opciones; j++){
if(rbuttons[control+j].checked){
if(rbuttons[control+j].value==correct[i]){
answers[i]= 1;
noPick="false";
break;
}
else{
answers[i]=2;
noPick="false";
break;
}
}
}
if(noPick=="true")
answers[i]=0;
control=control+opciones;
}
return answers;
}
It works great but while looking at my favorite browsers (FireFox, Chrome) error log it says:
TypeError: rbuttons[control + j] is undefined
Any clue on how to deal with this matter?
This probably means that control + j is greater than or equal to the length of the array rbuttons. There's no such array element as rbuttons[control + j].
You should learn how to use the JavaScript debugger in your favorite browsers! Debuggers are great. They let you watch this code run, line by line, as fast or as slow as you want, and watch how the value of control changes as you go.
You’ll watch it, and you’ll think “Oh! That line of code is wrong!”
You're looping through rbuttons.length times, but in each loop you're adding 2 to control. Using control to index your array, you're going to run past the end.
Does the index specified by control + j exist in the array? i.e: If that evaluates to 4, is there at least 5 items in the array?
Also, you should be using var i, var j, etc inside your for loop. Without it your variables are leaking into the scope this code is executed in (most likely the global scope, and that's not good) :)

Categories

Resources