Andrew Kim
Andrew Kim

Reputation: 3335

Why is the value of `this` in a dom event listener callback not the window?

Let's look at the following code:

const div = document.getElementById('foo');
div.addEventListener('click', function() {
  console.log(this);
});
<div id="foo">click me</div>

This button will always log the dom element I'm clicking. I've always known this to be true, and I know that I can use an arrow function here to make the value of this the window. We are assuming non arrow function syntax for this question.

To my knowledge, the value of this gets its value based on how the enclosing function is invoked. The callback of this event listener certainly doesn't get called on the dom element.

In my mind, when the div gets clicked, it adds the anonymous function to the message queue. When the queue is empty it invokes the anonymous function in a global execution context (perhaps this is where I'm wrong).

If it is in the global execution context where this anonymous function gets invoked, shouldn't the value of this be the window?

Which leads back to the title question, why is the value of this in a dom event listener callback not the window? (Assuming the callback is not an arrow function)

Upvotes: 0

Views: 167

Answers (2)

Ele
Ele

Reputation: 33726

The value of this within the handler

It is often desirable to reference the element on which the event handler was fired, such as when using a generic handler for a set of similar elements.

If attaching a handler function to an element using addEventListener(), the value of this inside the handler is a reference to the element. It is the same as the value of the currentTarget property of the event argument that is passed to the handler.

Upvotes: 0

Jack Bashford
Jack Bashford

Reputation: 44087

It's because it's a method attached to the div object - think of it like this:

const div = {
    addEventListener: function(event, callback) {...}
};

In this example, this would refer to div as you would expect.

This is what's actually happening in your code, only it's being defined differently.

Upvotes: 2

Related Questions