the counter of for of loop in javascript - javascript

I am studying javascript, and learning for loop. I am sure it's basic part but I can't get how the counter variable works..
I am making the battle application, and this is the function that is executed when user clicks the battle log, then it will show the last log and the index of it in console.log.
The battle log in the function is the array that stores nested arrays of users input.
let lastLoggedEntry;
function printLogHandler() {
let i = 0;
for (const logEntry of battleLog) {
if ((!lastLoggedEntry && lastLoggedEntry !== 0) || lastLoggedEntry < i) {
console.log(`#${i}`);
for (const key in logEntry) {
console.log(`${key} => ${logEntry[key]}`);
}
lastLoggedEntry = i;
break;
}
i++;
}
}
My question is the initial valuable is set in outside of the for loop(i = 0). but when the user clicks the battle log again, and this function executes again, how for loops has been saving the data of last i and logEntry's value? ( second time when user clisks, it will be i = 1, and logEntry = 0 already)
Also, how can it skip "let i = 0" from second time? because its not only for loop, it executes the function, I thought javascript reads let i = 0 again and it will reset to 0. ( it won't of course but I want to understand why)
Hopefully, you guys could help me out. Thank you,

A few things:
There is missing closure in the sample provided. There should be another closing bracket for the code to validate.
lastLoggedEntry must be defined as a variable before it is used.
It is not clear what the contents of battleLog are.
I think if you clarify these things it may be easier to answer your question.

Related

keeping localStorage objects that iterate whilst using clear() within the same function

I'm trying to clear all local storage when the user either completes the game loop or starts a new game, but also keep some values.
I can do this already with my sound values for volume:
// inside a conditional statement that fires when the user chooses to start a new game.
if (newGameBool === '1') {
var tst = myAu;
//myAu is the stored value that the user sets as sound using a range type input
localStorage.clear();
localStorage.setItem("Au", tst);//A newly cleared localStorage just got a new value, and it's the same as it was before.
UI.myLoad();//reload the function that uses LS to do things.
}
How do I do this for key's that have an iterating number attached to them?
Here is how I save them:
var i = +v + +1;
localStorage.setItem("v", i);
var vv = localStorage.getItem("v");
localStorage.setItem("LdrBrd_" + vv, JSON.stringify(LdrBrd));//saves all data with the iterating key name.
Calling them the way i did the sound function:
var gv = v + 1;//v calls the value from LS and adjusted for off-by-one error. gv is a local variable.
if (newGameBool === '1') {
var ldd, vg;
for (var ii = 0; ii < gv; ii++) {
var ld = localStorage.getItem("LdrBrd_" + ii);
if (ld != null) {
//these are the values that i want to pass beyond the clear point
ldd = JSON.parse(ld);//JSON string of data saved
vg = ii;//how many of them.
}
}
localStorage.clear();
for (var xx = 0; xx < vg; xx++) {
var nld = localStorage.getItem("LdrBrd_" + xx);
if (nld != null) {
localStorage.setItem("LdrBrd_" + ii, JSON.stringify(ldd));
}
}
localStorage.setItem("v", vg);
UI.myLoad();
}
I have been using console.log() in various spots to see what is going on. I comment-out the clear function just to see if the values were wrong and they don't save all all. I tried to make a fiddle, but the local storage wasn't working at all there. In visual studio, it works fine but the script to this file is almost 2000 lines long, so i tried to dress it up the best i knew how.
Thanks in advance for any help or guidance.
I was stuck on this for a few days, but i think i found something that will work, so i'll answer my own question in case there is value in posterity.
locatStorage.clear();
/* ^LS clear() function is above all new setItem codes, some variables are declared globally and some are declared at the top of the functional scope or as param^ */
var itemClass = document.querySelectorAll(".itemClass");//the strings are here
if (itemClass) {//make sure some exist
for (var p = 0; p < itemClass.length; p++) {//count them
mdd = JSON.parse(itemClass[p].innerText);//parse the data for saving
localStorage.setItem("v", v);//this is the LS item that saves the amount of items i have, it's declared at the top of the functions timeline.
localStorage.setItem("LdrBrd_" + p, JSON.stringify(mdd));//this setItem function will repeat and increment with 'p' and assign the right string back to the key name it had before.
}
}
The key is to keep the strings physically attached to an element, then call the class name. The i ran a loop counting them. 'mdd' will spit back each item i want. So then all that is left to do is re-set the item back to it's original status.
This has allowed me to create a way for my users to collect trophies and keep them even after clearing the localStorage when the he/she decides to start a new game.
I use CSS to hide the text from the string.
color:transparent;
In my gameLoop, i have a function that will read the saved strings and show them as cards just below the hidden strings.
Since you want to keep some values I recommend one of two things:
Don't call localStorage.clear() and instead only wipe out the values that you want using localStorage.removeItem('itemName'). Since you said the item names have a numeric component, maybe you can do this in a loop to reduce code.
Pull item(s) that you want saved first and restore them after calling clear(). This option is best if there are way more items that you want removed rather than saved (see below)
function mostlyClear() {
var saveMe = {};
saveMe['value1'] = localStorage.getItem('value1');
saveMe['anotherValue'] = localStorage.getItem('anotherValue');
localStorage.clear();
for(var prop in saveMe) {
if(!saveMe.hasOwnProperty(prop)) continue;
localStorage.setItem(prop, saveMe[prop]);
}
}

Why does this code create an infinite loop?

I have a JavaScript problem. I have a function that runs when I hit a button, the variables are changed via JavaScript. Everything in the function runs properly but this one last part:
else if (upgrade == "upgMiner4") {
var cost="500";
var qty="1";
var readCash=parseInt(document.getElementById("cash").innerHTML);
while (readCash >= cost) {
document.getElementById("cash").innerHTML += "-"+cost;
document.getElementById("cash").innerHTML = eval(document.getElementById("cash").innerHTML);
document.getElementById("gpt").innerHTML += "+"+qty;
document.getElementById("gpt").innerHTML = eval(document.getElementById("gpt").innerHTML);
}
}
When I run this code, it freezes and creates an infinite loop. I don't see the problem here, so I would like to know if you guys could help me, thanks!
-Zachucks
Your code inside the while loop does nothing to update readCash or cost, so if the condition (readCash >= cost) is true, this will never change, and the while loop will never exit.
I should add that a reader cannot tell what the evals are evaluating--so it's hard to be sure what is going on. However, notice you assign to readCash and cost exactly one time and that you never do this again. So why would it change?
Because you set readCash value only once and don't update it together with innerHTML with your div. That's why your loop doesn't end.
Working code:
while (readCash >= cost) {
document.getElementById("cash").innerHTML += "-"+cost;
document.getElementById("cash").innerHTML = eval(document.getElementById("cash").innerHTML);
document.getElementById("gpt").innerHTML += "+"+qty;
document.getElementById("gpt").innerHTML = eval(document.getElementById("gpt").innerHTML);
readCash = document.getElementById("cash").innerHTML;
}
neither readCash or cost variable are changing in the last while loop. That's why you're facing a loop. Probably you have to increment/decrement readCash or cost vars with a logic you're missing. Or maybe you don't actually need a while statement, but simply an if

Javascript weird variable connection / behaviour with each other

I've been programming in javascript (with a support from jquery) and I've run into some weird variable behaviour, which in I think is truly unexpected (or maybe I don't know something).
Basically, what I wanna do is to have one variable (zodziai) (array) be "stuffed" with arrays in one part of code and later on have those arrays removed by a click of buttons (one by one).
Also I still want to have those arrays saved in the end of the game even if the first variable is empty because of the button clicks.Easy, I thought to myself, so I've created another array variable (zodziai2) and equated those both in the beginning of the game (when the first one is full of arrays, ready to have them removed one by one.
Everything seems to fine until I check the value of zodziai2, second variable, in the end of the game. Even if it hasn't been touched throughout the process of removing elements from zodziai (first variable), somehow it turns out to be empty too in the end of the game.
Code: I declared both variable inside document.ready as = [];
$("#begin").click(function() {
//#begin is a button which starts the game
$("#enterwords").html("It's showtime!");
zodziai2 = zodziai; //zodziai is full of stuff, making zodziai2 the same
alert(window.zodziai2); //checking, zodziai2 seems to be equal to zodziai
taskai = 0;
maxtaskai = zodziai.length;
...
if (zodziai.length > 0) {
... stuff, just DOM.
...
}
});
And there goes the next button, which is responsible for removing one item from zodziai array. Somehow it gets removed from zodziai2 too.
$("#next").click(function() {
enword = $("#angliskas_zodis").val();
ltword = $("#lietuviskas_zodis").val();
//enword = enword.split("");
//atitinkamas = atitinkamas.split("");
if (enword == atitinkamas) {
...
zodziai.remove(random_skaicius); // removing one item from zodziai (no worries, it's a self written function, working as a bee
...
...
});
Later on, I define the third button, restart, in which zodziai2 is now empty as is zodziai. How can zodziai2 be empty if the code is only "playing" with zodziai? What am I missing??
$("#restart").click(function() {
zodziai = zodziai2; //should be full of stuff, but is certainly not :(
random_skaicius = 0;
ilgis = 0;
zodis = "";
atitinkamas = "";
tempzodislt = "";
taskai = 0;
maxtaskai = 0;
klaidingi = [];
$("#angliskas_zodis").val("");
$("#lietuviskas_zodis").val("");
surasymas(window.zodziai2);
alertify.alert("Drop us a line if you think this function would be useful :)");
});
Just a pointer. I see you write a statement zodziai2 = zodziai. What it means that both variables point to the same memory location of the array. If you remove an element from zodziai, it'll be removed from zodziai2 too. Does this helps?

Honestly hard to explain.. I use something like a=b, then a++, but b changes. Except, these are Arrays

Well my short and easy to explain explanation can be this. I have 2 arrays, FilterList and GamesReset. Whenever this function I have works and filters out some games with check boxes and a drop down menu, the function starts off with something like FilterList=GamesReset;. This functions seems to work fine until I filter out ages for the game. The function never touches GamesReset unless it's something like while(i<GamesReset.length){} or FilterList=GamesReset;. And the only tool I use when I filter games is FilterList.splice(i,1);. Now with that, GamesReset definitely, should never change as far as I know. I have it to reset FilterList, then depending on what needs to be filtered out, it will start removing those games from the FilterList. The problem I have, is that, GamesReset also becomes filtered. Which, does not make any sense at all. So like my title, it's just like saying b=0;, a=b;, a++;, and now b equals 1.
Now, I think that's the best/shortest way I can reveal this problem, without overdoing it with my bad habit of explaining things to people. I have a webpage currently available if anyone would like to see whats going on in action, because I wouldn't get what's going on with GamesReset either if I were you, here (url removed, read edit). To get the error working, just change the age to 10 without checking any boxes. The bottom paragraph is the GamesReset array (using <br> to separate each array), and it's the one that changes when I'm only changing FilterList in the JavaScript. The actual codes if you view the page source may be a little off compared to when I mentioned above, but it's pretty much 100% the same thing. I also wanted to have the codes available without a url and on this page, but I can't figure out how to do that with the html tags included.
Actually, here's the JavaScript function. I just figured out the 4 spaces thing when my question was rejected.
function SearchFilter() {
Games = GamesReset;
plat = document.getElementById('platformcheck').checked;
rpg = document.getElementById('rpgcheck').checked;
puzz = document.getElementById('puzzlecheck').checked;
hybo = document.getElementById('hybocollectcheck').checked;
ages = document.getElementById('agescheck').value;
if ((!plat) && (!rpg) && (!puzz) && (!hybo)) {
FilterList = Games;
} else {
FilterList = [];
i = 0;
while (i < Games.length) {
Set = '';
Set = Games[i];
Set = Set.split('</>');
StrFind = Set[0];
if (
(plat && (StrFind.search(',platform,') > -1)) || (rpg && (StrFind.search(',rpg,') > -1)) || (puzz && (StrFind.search(',puzzle,') > -1)) || (hybo && (StrFind.search(',hybocollect,') > -1))) {
FilterList.push(Games[i]);
}
i++;
}
// so by now, we should have the filtered array
}
//seperate filter for ages
i = 0;
while (i < FilterList.length) { //The problem should definitely start here
Set = '';
Set = FilterList[i];
Set = Set.split('</>');
StrFind = Set[1];
if ((Math.abs(StrFind)) > ages) {
FilterList.splice(i, 1);
} else {
i++;
}
}
GL.innerHTML = GamesReset.join('<br>');
}
As a reminder, the problem starts when the age filter is working. And the only thing it does is FilterList.splice(i,1);. But it ends up changing GamesReset. I changed this function a bit when I added Games=GamesReset;, but that was another test to try and make sure GamesReset doesn't get filtered like FilterList, but it still does.
EDIT: I removed my url since the answers definitely explained everything, so there's no need for it now.
Arrays are not copied when assigned, both variables will refer to the same data. Here is a post that goes into detail on this: Copying array by value in JavaScript
It makes perfect sense since variables are just references to objects in memory. One object can have several references. Consider this:
var a = { foo: 'bar' };
var b = a;
// b is now a reference to a and they both point to the same object
b.foo = 'doe';
alert( a.foo ); // alerts doe
The same goes for arrays. So when you do FilterList = GamesReset you are not copying the array - you are just assigning the same array to another variable. Any mutations or changes made to either reference will be reflected in all references.
To create a copy of an array you can use slice:
FilterList = GamesReset.slice();

Javascript - Prompt for values (and add values to array) until user inputs a specific value

Ladies and gentlemen,
I'm stuck. I've been pondering this (and obviously have failed since I'm asking for your valuable assistance) in trying to get my code to work.
I need to come up with a simple (...I'm sorry, i'm new to this) code that prompt users to keep entering names using a loop. If the user does not enter 'q'(without quotes) and if the value entered is NOT null, then the value entered should be added to the array (in my case, names).
If the user enters 'q', the loop should stop, 'q' will not be entered in the array and the list of names should be printed (through the second function in my code).
Here's what I have so far... I can make the code work if I tell the loop to run i<5... it runs 5 times and then it stops. But it fails if i do i < names.length..it causes it say that length is null or not an object (on line 10). That's problem one. And for the life of me, I can't figure out how to add the logic that will run the loop until user enters q.
Please help!
Thank you.
function getNames(){
var names = new Array();
for(i=0;i<names.length;i++){ /*if i do i=0;i<5;i++, the code works; it doesn't with this*/
names[i] = prompt("Enter an item to add to the Name list (enter \'q\' to quit","");
}
printNames(names);
}
function printNames(names) {
for(x=0; x < names.length;x++){
document.write(names[x] + '<br />');
}
}
getNames();
printNames();
I am sure somewhere in your class/book it talks about while loops. So you want to use a while loop if you want them to keep entering without a limit.
while (myCondition===true) {
//do something
}
Now look at your for loop and figure out why it is failing.
for(i=0;i<names.length;i++)
Look at what it is doing:
i = 0
names.length = 0
Is 0 < 0?
Well to start with Problem 1:
Your names array begins with a length property of 0 and so your first for loop doesn't run because 0 is not less than 0.
Which leads to Problem 2:
Again since nothing was entered into your names array your second for loop again does nothing and doesn't execute document.write because the length property of your array is still 0.

Categories