admin管理员组文章数量:1236700
I read some other answer about this topic but I'm not sure I understand how this
keyword works inside addEventListener
.
const button = document.querySelector('button');
function foo() { console.log(this) }
button.addEventListener('click', foo);
foo
is a regular function inside addEventListener
, it's not a method on button
object. When foo
is called should be executed in the context of the global object, therefore this
should be equal to window
and not to button
.
Looks like a situation similar to this example:
const obj = {
method: function (cb) {
console.log('method', this); // `this` === `obj`
return cb();
}
};
obj.method(function() {
console.log('cb', this); // `this` === `window`
});
Where obj
could be considered as button
, method
could be addEventListener
and cb
the callback inside addEventListener
.
I know I can use bind
to change the context of this
but I want to understand more in depth why it works like that.
Why this
inside addEventListener
callback is invoked on the context of the current element instead of the global object?
I read some other answer about this topic but I'm not sure I understand how this
keyword works inside addEventListener
.
const button = document.querySelector('button');
function foo() { console.log(this) }
button.addEventListener('click', foo);
foo
is a regular function inside addEventListener
, it's not a method on button
object. When foo
is called should be executed in the context of the global object, therefore this
should be equal to window
and not to button
.
Looks like a situation similar to this example:
const obj = {
method: function (cb) {
console.log('method', this); // `this` === `obj`
return cb();
}
};
obj.method(function() {
console.log('cb', this); // `this` === `window`
});
Where obj
could be considered as button
, method
could be addEventListener
and cb
the callback inside addEventListener
.
I know I can use bind
to change the context of this
but I want to understand more in depth why it works like that.
Why this
inside addEventListener
callback is invoked on the context of the current element instead of the global object?
- developer.mozilla/en-US/docs/Web/API/EventTarget/… – Jay Harris Commented Aug 25, 2018 at 11:52
-
1
"
foo
is a regular function insideaddEventListener
, it's not a method onbutton
object." - that doesn't matter. If you callfoo()
, then yes you won't get athis
value (or the window in sloppy mode), but when you useaddEventListener
then it will call the function on the button. Just as if in yourobj
example themethod
would docb.call(obj)
– Bergi Commented Aug 25, 2018 at 18:26 -
Also consider the old style:
button.onclick = foo
. There the handler actually is a kind of method :-) – Bergi Commented Aug 25, 2018 at 18:28 - This problematic is very well explained in MDN Docs. (Updated link of @JayHarris) – user11484628 Commented Jul 11, 2021 at 15:25
5 Answers
Reset to default 22If we are using functions which have been defined using function keyword as an event handler, then that event handler function executes in the context of the element on which event was binded
button.addEventListener('click', foo);
so, in this case, this
value inside foo will be button
element.
If we use arrow functions instead of them then this
value will be the window object
The reason is this
in an arrow function has the same value as the context in which the arrow function was created
button.addEventListener('click', () => { console.log(this) // window } );
More about lexical this What is lexical 'this'?
While we know that event listeners are executed with 'this' set to the event target, the below lines of code inside the EventTarget.prototype.dispatchEvent method in the EventTarget link that you found will answer your question as to how it is implemented.
for (var i = 0, l = stack.length; i < l; i++) {
stack[i].call(this, event);
}
The 'stack' array has the callback functions and they are invoked using .call by passing in the event target instance (this) and event as arguments.
Event listeners are executed with this
set to the object that triggered the event, as one listener can listen to events of many objects.
A regular function invocation however does not set this
if the invocation expression does not contain a member access via .
. In those cases, without "use strict"
active, this
will bee the global context, which is window
in the browser.
If you want this
for cb
to be obj
, you could replace cb()
with cb.apply(this)
, which would set cb
's this
to that of the enclosing function.
A final warning: these this
mechanics only work for functions defined with the function
keyword (and similar mechanics). The this
inside of an arrow function bees locked to that of the enclosing scope at the time of definition.
As event handler is a type of callback, they are passed as a parameter to the function. Let's create a simple function and passed one callback as a parameter to it and see how it actually works.
function testCallBack(fn){
console.log('inside testCallBack');
fn('Hello I am a callBack')
}
testCallBack(foo);
function foo(param){
console.log(param);
}
// Outputs:
inside testCallBack
Hello I am a callBack
Every scope in JavaScript has a this object that represents the calling object for the function.
That's the reason why this
inside addEventListener callback is invoked on the context of the current element instead of the global object.
Refer below code for more clear understanding:
function sayNameForAll() {
console.log(this.name);
}
var person1 = {
name: "Rajat",
sayName: sayNameForAll
};
var person2 = {
name: "pldg",
sayName: sayNameForAll
};
var name = "Sidd";
person1.sayName(); // outputs "Rajat" here calling object is person1, so this represents person 1
person2.sayName(); // outputs "pldg"
sayNameForAll(); // outputs "Sidd"
So when you call button.addEventListner('click',foo)
, your calling object is button
.
Just like you can use bind
or call
to set this
to whatever you want, the browser APIs can also call your functions with any value set to this
. It’s used in a bunch of weird ways and isn’t very consistent. Outside of classes and methods, this
is more like a secret extra argument to a function. In this case you could avoid needing it by getting the button element from event.target
.
本文标签: javascriptthis keyword inside addEventListener callbackStack Overflow
版权声明:本文标题:javascript - this keyword inside addEventListener callback - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1739792796a2191593.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论