Why does this javascript for loop cause an early exit? [duplicate] - javascript

This question already has an answer here:
(infinite?) loop in javascript code
(1 answer)
Closed 5 years ago.
Right now I am really stumped. I have a short function, called "validate", and for some reason the for loop I have prevents an outer for loop from running.
Here it is breaking by only printing out the first entry:
function validate(str) {
for(i=0; i<str.length; i++) {
// do nothing
}
return str;
}
And here's the version that works:
function validate(str) {
/*for(i=0; i<str.length; i++) {
// do nothing
}*/
return str;
}
Here is my fiddle.
Here is the sample text file.

Try encapsulating your variable i. var i = 0;
function validate(str) {
for(var i = 0; i < str.length; i++) {
// do nothing
}
return str;
}
Without the var you are adding it to the global scope or the window object

Related

Curious to know step by step Process of for loop which involves let and var [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 3 years ago.
I have 2 simple code snippet about for loop involving let and var separately.
First code which has a variable declared with let
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
so it will show o/p like this
0123456789
but if I replace let with var like this
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
it will print 10 for ten times.
I know it is something related to function level scope and block-level scope, but want to clearly understand step by step process of execution.
Thanks in advance.
The reason why you are only printing 9 is that the callback function is executed after the loop is done. Which means that i is 9.
You can:
If you are trying to print 1 - 10 after 1 sec, you can loop in the callback function. Like:
setTimeout(function() {
for (var i = 0; i < 10; i++) { //Put the loop inside the setTimeout db function.
console.log(i);
}
}, 1000);
If you are trying to print every one sec, you can pass the i as the 3rd parameter on setTimeout
for (var i = 0; i < 10; i++) {
setTimeout(function(o) { //Receive it on variale o
console.log(o);
}, 1000 * i, i); //Pass the i as third parameter
}
Doc: setTimeout

JavaScript Why does the index of a for loop add one when adding eventlisteners [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I have a question which might sound silly. In the code below there are 2 console.log(i) statements. I want to know why does the second console.log(i) statement returns value of 2 and not 1 as the former on the first iteration (i.e. 1st statement i=n, 2nd: i=n+1). Shouldn't both be equal to 1 until the end of the loop?
function toggleWrapper(){
var el1 = document.querySelectorAll('[class="tCell entryDesc"]');
for (var i = 1; i < el1.length; i++) {
console.log(i);
el1[i].addEventListener('click', function(ev){
console.log(i);
var el2=document.querySelectorAll('[class="additionalInfoContainer"]');
if (el2[i-2].clientHeight) {
el2[i-2].style.maxHeight = 0;
}
else{
el2[i-2].style.maxHeight = el2[i-2].scrollHeight +"px";
}
},
false);
}
}
The problem is that the variable i, within each of your addEventListener() functions, is bound to the same variable outside of the function. simply change your for loop to :
for (let i = 1; i < el1.length; i++)
In the loop with let based index, each iteration through the loop will have a new value of i where each value is scoped inside the loop, so your code would work fine.
i think is something in your code because if you try to make a for loop with two "console.log()" it doesn't do that

Javascript onclick attachment indexer issue [duplicate]

This question already has answers here:
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 6 years ago.
I have problem with the following 'registerHandlers' javascript function. When I am trying to attach the onclick even, it always displaying '3'. Here how it should work;
An alert should display anchor's zero-based index within a document instead of following the link.
For example, in the document below, the alert should display "2" when Google anchor is clicked since it is the third anchor element in the document and its zero-based index is 2.
Here the script and test page in JSFiddle
function registerHandlers() {
var as = document.getElementsByTagName('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
alert(i);
return false;
}
}
}
This should work :)
function registerHandlers() {
var as = document.getElementsByTagName('a');
var j = 1;
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
alert(j);
j++;
}
}
}

Why is bracket notation not working here? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I am writing a function to fire a series of click handlers with a given time interval in between.
function play(step){
var buttons = document.querySelectorAll('.age');
buttons[0].click();
for (var i = 1; i < buttons.length; i++){
setTimeout(function(b){
b.click();
}, 300 + (step*i), buttons[i]);
}
}
The above function works as intended, however, the following version which to me seems like it should be equivalent, does not work:
function play(step){
var buttons = document.querySelectorAll('.age');
buttons[0].click();
for (var i = 1; i < buttons.length; i++){
setTimeout(function(b){
console.log(i);
console.log(b);
b[i].click();
}, 300 + (step*i), buttons);
}
}
I was getting the following error:
TypeError: Cannot read property 'click' of undefined
After checking, I find that console.log(i) is printing 6. So, apparently, the attribute access isn't occurring until after the loop is over, which explains the error! But what exactly is going on here? I'm relatively new to javascript, but is this behavior the result of the anonymous function acting as a closure? That doesn't sound like the right explanation to me. Is it because setTimeout is delaying the evaluation of the anonymous function?
ETA:
I did an experiment:
function sleep(ms){
var current = new Date().getTime();
while (current + ms >= new Date().getTime()){};
}
function play(step){
var buttons = document.querySelectorAll('.age');
buttons[0].click();
for (var i = 1; i < buttons.length; i++){
setTimeout(function(b){
console.log(b);
console.log(i);
b[i].click();
}, 300 + (step*i), buttons);
sleep(1000);
}
}
when I run play(200) I get the same error message, so sleep(1000) should be enough time to make sure that the loop hasn't exited before the first timeout is up, no?
It's because variable in for loop is the same in each iteration (same reference) and when setTimeout is running the for loop has ended so the i variable will be last value of the loop, to fix this you can create a closure with i variable:
function play(step){
var buttons = document.querySelectorAll('.age');
buttons[0].click();
for (var i = 1; i < buttons.length; i++){
(function(i) {
setTimeout(function(b){
console.log(i);
console.log(b);
b[i].click();
}, 300 + (step*i), buttons);
})(i);
}
}

Adding class to div with onclick function [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I tried to find some way to solve my problem, which is to add class to the divs when I click on them, but I can't make it work.
var el = document.getElementsByClassName('applications');
var i;
for (i = 0; i < el.length; i++) {
el[i].addEventListener("click", function() {
if (el[i]) {
el[i].className += el[i].className ? ' openDiv' : 'openDiv';
}
});
}
I have the 'for loop' because I used getElementsByClassName which gives a node list. I also created a codepen example:
http://codepen.io/anon/pen/dGqmMy
Instead of using complex string manipulation, use classList:
el[i].classList.add('openDiv');
I believe you might need to add a closure for the eventListeners to work.
So this would be considered as a solution:
var el = document.getElementsByClassName('applications');
var i;
for (i = 0; i < el.length; i++) {
(function (i) {
el[i].addEventListener("click", function() {
if (el[i]) {
el[i].classList.add('openDiv');
}
});
})(i);
}

Categories