0

I have trouble understanding relation between loop variable and anonymous functions in JavaScript.

This example code is from web page i was working and testing some things. And to my surprise code worked how i wanted it to but i cant understand exactly why.

Here is HTML snippet that might be relevant for context:

<body style="background-color:blue">
        <div class="header">
            <h1>Trivia!</h1>
        </div>

        <div class="container">
            <div class="section">
                <h2>Part 1: Multiple Choice </h2>
                <hr>
                <h3>What song was played that day?</h3>
                <div >
                    <button>A</button>
                    <button>B</button>
                    <button>C</button>
                    <p id="ABC"></p>
                </div>

Here i wanted to add event listener to each element and have button turn green if answer was correct(button A clicked) and red if incorrect.I wanted to do with loop which attaches event listener and handler function to each button.Here is the script:

<script>
            var a=document.getElementsByTagName("button");
            for(let i = 0; i < a.length; i++)
            {
                a[i].addEventListener('click', function(event){
                let paragraph=document.getElementById("ABC");
                for(let j=0; j<a.length; j++)
                {
                    if(a[j].style.backgroundColor=="green"||a[j].style.backgroundColor=="red")
                    {
                        return;
                    }
                }
                if(a[i].innerHTML=="A")
                {
                    paragraph.innerHTML="Correct";
                    a[i].style.backgroundColor="green";
    
                }
                else {
                    document.getElementById("ABC").innerHTML = "Incorrect";
                    a[i].style.backgroundColor="red";
                }
                });
            }
            </script>

What confuses me is that this code works. And i cant understand why exactly. Because i excepted that by the time handler function gets run (after script gets executed and event listener added and then click detected) variable i value would be 2.And therefore in handler function run on each button if(a[i].innerHTML=="A") would refer to last button.

But what actually happens is in chrome debugger each time i pause on click event and go inside handler function attached to each button i in each function is of different value and a[i] refers to button that it should.So code does work due to i changing in each function.

While inner j loop behaves as expected inside function each time.

But as mentioned shouldn't outer i loop get executed first setting i to 2 (after last iteration) then function gets called on click and a[i] is encountered in code contained in function but since its run after loop attached each function already i is by then 2 and a[i] refers to only last button.Not correct one in terms of problem being solved.

This is really confusing to me and shows i dont understand how relation between loop variable and anonymous function works exactly.Hopefully someone can clear up confusion.

  • When you use `let` to declare the iteration variable `i`, you get a new `i` for each pass through the loop body. If you had used `var`, it would have behaved (badly) as per your description. – Pointy Nov 17 '22 at 12:02
  • @Pointy Thank you. So it would equivalent of declaring variable in loop in c – 21CenturyBoy Nov 17 '22 at 12:55
  • @Pointy Something similar like for(int i=0;i<3:i++) and then in loop body its as if new was was declared in like i=0; i=1;i=2 and that new i is used in function – 21CenturyBoy Nov 17 '22 at 12:57
  • See the linked duplicate question. – Pointy Nov 17 '22 at 12:58
  • @Pointy thanks i did. But there is still one confusion left since answers are too advanced for me. When in answer new binding is mentioned what exactly would it mean? I understand that i gets new binding on each iteration but does that mean in other words that new i gets declared on each iteration and exists in said block only.Therefor there are multiple is that exist now? But how does each function when called later know later on which i to refer to for a[i] if i is bound to multiple values bound to one same name in memory? – 21CenturyBoy Nov 17 '22 at 13:45
  • The closures formed when you create the event handlers "know" which `i` to use, because when they are created there is only one `i`. Yes, a new `i` is created on each iteration, but each handler only knows about one of them. – Pointy Nov 17 '22 at 15:13

0 Answers0