0
pattern.forEach( function(elem, index) {

            setTimeout(yo(elem),index*1000);

                function yo(elem){
                    console.log(elem);
                switch (elem) {
                    case 'blue':
                        // statements_1
                        $('#blue').css('background-color','grey');
                        bsound.play();
                        setTimeout(function(){$('#blue').css('background-color','blue');},500);
                        break;
                    case 'green':
                        // statements_1
                        $('#green').css('background-color','grey');
                        gsound.play();
                        setTimeout(function(){$('#green').css('background-color','green');},500);
                        break;
                    case 'red':
                        // statements_1
                        $('#red').css('background-color','grey');
                        bsound.play();
                        setTimeout(function(){$('#red').css('background-color','red');},500);
                        break;
                    case 'yellow':
                        // statements_1
                        $('#yellow').css('background-color','grey');
                        ysound.play();
                        setTimeout(function(){$('#yellow').css('background-color','yellow');},500);
                        break;

                }

            }
            });

Hey, guys, I am trying to build a Simon game. Now as the game follow the computer will generate random patterns. Every color has its specific sound which will be played. Now the logic I am using here is we will loop on pattern array using foreach method. At every element, I will call settimeout callback function with index*1000. I am multiplying index with ms so there is a gap between every call. Now if I have a pattern array of say [‘red’] it works. for [‘red’,‘yellow’] It will simultaneously play both blocks sound for yellow and red and will also change the color of those blocks to gray and changing it back to their original color (problem is it is doing that simultaneously). if [‘red’,‘yellow’,‘red’] it will do the same thing as for [‘red’,‘yellow’] (meaning it skips the red color sound). Can any body please tell me why this is happening.I searched stackoverflow and people suggested to use index*ms to get the desired delay.....

Airas Yaqub
  • 57
  • 2
  • 12
  • 1
    The first argument to `setTimeout` needs to be a function reference, not a call to the function. – Barmar Dec 29 '17 at 11:55
  • @Barmar I have used this and it works setTimeout(yo.bind(window,elem),index*1000); But please can you explain why it was'nt working before. I want to know the flow of the program and the reason it wasnt working – Airas Yaqub Dec 29 '17 at 12:09
  • Instead of passing a function to `setTimeout`, you were calling the function immediately and passing its return value to `setTimeout`. – Barmar Dec 29 '17 at 12:11
  • Isn't that what it says in the first line of the first answer to the duplicate question? – Barmar Dec 29 '17 at 12:12
  • Thats why when I have ['red','yellow'] array. settimeout will see a function call yo(elem) it for each element it calls the function and return nothing so we will have settimeout(undefined,index*1000). After the given ms pass settimeout will see undefined in place of call back function and do nothing. Right is that whats happening ? – Airas Yaqub Dec 29 '17 at 12:26
  • Yes, exactly. `setTimeout(yo(elem), index*1000)` is equivalent to `var temp = yo(elem); setTimeout(temp, index*1000);`. In this form it should be obvious what's happening. – Barmar Dec 29 '17 at 12:28
  • @Barmar Thanks, mate. I have the last question if u don't mind to answer. For example, if I am using for loop instead of for each I would do something like this `setTimeout((function(j) { genersounds(pattern[j]);}).bind(null,i),i*800);` . I dont understand why we have to self invoke a function that case. I tried to do this without using self invoking function i.e : `setTimeout(function(j) { genersounds(pattern[j]);}.bind(null,i),i*800);` but it didnt work – Airas Yaqub Dec 29 '17 at 12:46
  • See https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – Barmar Dec 29 '17 at 12:47
  • Because `for` loop doesn't create a new variable each time, so all the closures are bound to the same variable. You need the IIFE to create a function scope to get a new variable. – Barmar Dec 29 '17 at 12:49
  • @Barmar I don't understand. Sorry, I am just noob with closure right now. Why do we have to use IIFE even though we are binding every setimeout inner function with the current value of 'i'. Maybe I am getting wrong the flow of code with settimeout. Here what I understand. For loop will start, at first iteration compiler will see setimeout and its given 'ms' so will not execute it. Also at every iteration, we are binding 'i' with the anonymous function of setimeout. When the whole loop will end browser will start executing the anonymous functions and each function will have its own val of 'i' – Airas Yaqub Jan 01 '18 at 16:12
  • So if we use IIFE will it not be executed every time even during the for the loop. Our whole intention is to give a respective value of 'i' to each settimeout function using bind(). I don't understand why are we using IIFE. – Airas Yaqub Jan 01 '18 at 16:15
  • A closure captures the location where the variable's value is stored, not the value itself. When you use a `for` loop, it doesn't create a new variable location for `i` each time, it just updates its contents. All the closures refer to that same location, so when they're executed by `setTimeout()` they have the last value. See [How do Javascript closures work](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) – Barmar Jan 01 '18 at 20:52

0 Answers0