A most weird javascript behaviour

A most weird javascript behaviour
0

#1

Hi,

As i was doing my Twitch Tv project , i came across a problem where by in the for loop only the last stream was returning, i was suggested to use closure …It worked but i am unable to understand it …

For example here -

for(var i = 0;i< 10; i++){
for(var k = 0; k < 5; k++){

console.log(i);
}
}

Now my logic says the “i” will not console log after k fails to satisfy the value but it just keeps printing ignoring value of k by acessing the value of i outside of it …My fiddle here - https://jsfiddle.net/jinisner/Lww7akjq/

Kindly help me understand closure as its making all my programming understanding go haywire …


#2

The output of your program above is this

Notice, it’s printing the value of “i” five times (5x, i.e. which is your k loop) for each unique i value.

What are you exactly trying to do? Can you let us know the output/sequence that you want.

You’re not doing anything with the value of k (you’re not printing it). You’re just using it as a counter for the inner loop, causing console.log(i) to print 5x.


Maybe this will help you see it more clearly If you replace your console.log statement with

console.log(i, k);

 0 0
 0 1
 0 2
 0 3
 0 4
 1 0
 1 1
 1 2
 1 3
 1 4
 2 0
 2 1
 2 2
 2 3
 2 4
 3 0
 3 1
 3 2
 3 3
 3 4
 4 0
 4 1
 4 2
 4 3
 4 4
 5 0
 5 1
 5 2
 5 3
 5 4
 6 0
 6 1
 6 2
 6 3
 6 4
 7 0
 7 1
 7 2
 7 3
 7 4
 8 0
 8 1
 8 2
 8 3
 8 4
 9 0
 9 1
 9 2
 9 3
 9 4

#3

@owel - thanks for your reply , so as i said earlier - here is my outer loop-

for(var i = 0;i< 10; i++){


}

which should run for i<10 , then i add another loop inside it

for(var i = 0;i< 10; i++){
for(var k = 0; k < 5; k++){

console.log(i);
}
}

this loop should run for k < 5 and do what ever i want to do , why it run 10 times ?

How can i make i print only 0,1,2,3,4

Or am i confusing it with closure as the  only way i could make my code work with another for loop was by doing  this ---

////-------------------
for(var k = 0; k < following.length; k++){
    (function(k){
      
      
     ////----do stuff here
     
  
    
    
     if (ourData2.stream !== null) {
        
       /////---Access K here for each individual value
     
    $("#info").prepend("<div class = 'row'>" + "<div class = 'col-md-4'>" + "<img src = ' " + logo + " ' height = '100px' width = '100px'>" +
                       "</div>" + "<div class = 'col-md-4'>" + "<a href=https://www.twitch.tv/" + following[k] + ' target="_blank">' +  name + "</a>" + " is online"  + "</div>" + "<div class = 'col-md-4'>" +
                       
                       status + "</div></div><p></p>");
      
     }
     
   else if(ourData2.stream === null){

//////////-----------Access k here for each value

       
 var myRequest4 = new XMLHttpRequest();
   var url4 = "https://wind-bow.glitch.me/twitch-api/channels/" + following[k];
   myRequest4.open("GET", url4, true);
     
   myRequest4.onload = function (){
 
    var ourData4 = JSON.parse(myRequest4.responseText);
     if(ourData4.logo !== null){
     var logo4 = ourData4.logo;
     }
     else {
       logo4 = "http://wtctheology.org.uk/wp-content/forum/uploads/2015/10/OpenWTC_offline_LOGO.png";
     }
      var name4 = ourData4.display_name;
      $("#OffInfo").prepend("<div class = 'row'>" + "<div class = 'col-md-4'>" + "<img src = ' " + logo4 + " ' height = '100px' width = '100px'>" +
                       "</div>" + "<div class = 'col-md-4'>" + "<a href=https://www.twitch.tv/" + following[k] + ' target="_blank">' + name4  + "</a>" + " is Offline"  + "</div>" + "<div class = 'col-md-4'>" +
                       
                       "Offline" + "</div></div><p></p>");
    
    
    
   };
   
     
   
     }
  
   myRequest4.send(); 
       
   };
      
       myRequest2.send();
 
    })(k); ///////-------------call it  here 
     

//////-----------------------

Regards


#4

Ok i got it, it continues the console log as the outer loop still has to fulfill its condition, getting confused with closure, IIFE etc … thanks


#5

I’ve edited your post for readability. When you enter a code block into the forum, remember to precede it with a line of three backticks and follow it with a line of three backticks to make easier to read. See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.


#6

@rmdawson71 - thanks, i will surely post as you have suggested …

Regards


#7

But this has nothing to do with closure, IIFEs, etc. This is just normal loop operation. It is doing exactly what you are telling it to do and doing exactly what it would do in any language. I suspect that if you think that you did not understand it because of closure or IIFEs, then you have a fundamental misunderstanding of how loops work.

Your statement Now my logic says the “i” will not console log after k fails to satisfy the value but it just keeps printing ignoring value of k by acessing the value of i outside of it makes me think that maybe you think the outer loop will finish before the inner loop runs? Or something like this?

But again, none of this has anything to do with closure or IIFEs. Those are both important topics, but that is not what is happening here.

To elaborate of Owel’s example, maybe this will help:

for(var i = 0;i< 10; i++){
  console.log('\n\nBeginning a new outer loop, i = ' + i);
  for(var k = 0; k < 5; k++){
    console.log('Inside inner loop, i = ' + i + ' and k = ' + k);
  }
  console.log('Back in outer loop after completing inner loop, i = ' + i);
}

Run that and check your console. Do some more research on for loops.


#8

@ksjazzguitar - yes it has noting to do with closure, but the moment i came across the looping problem in javascript and when the values where not getting printed as per the assumptions, like 0,1,2,3,4 etc but only the final value, i got confused …

Now i am thinking that as javascript was browse end it needed to hold on to things and not let them go so that it can perform operations at browser end itself , leads to all this logic of remembering scope etc …

It will take some time to get adjusted to new concepts :slight_smile:

Thanks


#9

Again, scope really isn’t an issue here. And again, this functions exactly the same in any programming language (at least any I’ve learned). What if we came at this from the opposite direction - can you show us what you think this code should output? Maybe that would help us to understand what you’re not understanding.

for (var i=0; i<10; i++) {
  for (var k=0; k<5; k++) {
    console.log(i);
  }
}

What do you think this should output?


#10

I guess now that i have already tried it , i can say , it will for the outer loop value(i) of 0 print (0,1,2,3,4)(k) , then again for value of 1(i) for outer loop (0,1,2,3,4)(k) … i was confused when i saw 5 for k , but now i know that javascript holds on to the value … still a bit confusing though…

Thanks


#11

It’s not “holding on to the value” in the sense that it’s doing something anything weird, it’s doing exactly what it is supposed to do. Once you set the value of i it will stay that value until you change it, or if i goes out of scope. But since everything is in the same scope here, scope is not relevant. Also not relevant are closure and IIFEs.

Is it the “5” that’s bothering you? If I can steal a graphic from my buddy owel:

ik

You need to understand what that “5” is and what it isn’t. But in order to understand that, we need to understand that console.log is not technically part of JavaScript, but is part of the browser. Every browser chooses how to implement console.log. That “5” is not being output from JavaScript. JavaScript is outputting “1” by the console.log, and the console puts it on it’s own line. But your program (because of the k loop) outputs each number 5 times. Rather than write the same line five times in a row, your console (and most if not all as far as I know) just writes it once and puts the “5” there to tell you that it did it 5 times in a row. Your console does this to save space and make things more readable. So, that “5” in the blue circle is not coming from your program but is coming from the console not wanting to write the same number over and over. If you change the number in the k loop, the number in the blue circle will change.

So, to refresh, your snippet:

for (var i=0; i<10; i++) {
  for (var k=0; k<5; k++) {
    console.log(i);
  }
}

The i loop sets i to 0, then the k loop logs it to the console 5 times. Because the console doesn’t want to write the same thing 5 times in a row, it writes it once and tells you that there are 5 lines in a row writing the same thing. Then your i loop sets i to 1 and the k loop logs it to the console 5 times …

I hope that clears it up.


#12

@ksjazzguitar - thanks for the very detailed explanation …

Regards