Skip to content Skip to sidebar Skip to footer

Javascript Closure Within Eventlistener

Solution 1:

What you are doing here is directly calling the function clicked instead of setting it as an event handler.

i don't get why with closure onclick doesn't log the 'pass' string when button clicked instead does log out the i.

well, your closure was

returnfunction(){
  console.log(i);
}

Why would that log anything except i ?

The function that creates this closure should log "pass" five times during page initialization (as you call five times in the loop, each time it logs a line and returns the closure).

You could use bind.

nodes[i].addEventListener('click', clicked.bind(nodes[i], i));

This will give you i as a parameter to the function, so that you can do

console.log("pass", i);

Solution 2:

Attempting to answer the original question as asked...

but i don't get why with closure onclick doesn't log the 'pass' string when button clicked instead does log out the i

Go back to your code without the commented out section...

<button>test</button><button>test</button><button>test</button><button>test</button><button>test</button><script>var nodes = document.getElementsByTagName('button');
    functionclicked(i) {
        console.log('pass');

         //Closurereturnfunction(){
          output(i);
         }

    }
    functionoutput(i) {
        alert('The value of the closure i for this button is: '+i);
    }
    for (var i = 0; i < nodes.length; i++) {
        nodes[i].addEventListener('click', clicked(i));
    }
</script><style>html {
        counter-reset: button-count -1;
    }

    button:after {
        content: ' 'counter(button-count);
        counter-increment: button-count;
    }
</style>

(I also added a little extra to help explain)

When you initialise the event listeners in the for loop, you are passing the return value of clicked(i) as the function pointer to be called when the click occurs on node[i]. In your original code, the return value is a reference to an anonymous function defined as:

function(){
  console.log(i);
 }

So this is what is executed when you click button i - not clicked. clicked is only executed during the for loop. You will see pass one time for each button in the console due to the for loop.

The lexical scope for the anonymous function includes the scope of it's containing function clicked so the parameter i is in scope for the anonymous function. Each time clicked terminates, during the for loop, a separate closure is created on the parameter i, preserving it's value for that particular call.

In the code above, I created a function called output that receives a parameter i, so this

function(){
  output(i);
}

... is called when you click button i: also having a closure on i.

I also added some CSS styling to number the buttons.

Post a Comment for "Javascript Closure Within Eventlistener"