Reputation: 2607
Consider the following code:
var myObject = {
items : ... //some DOM elements
,attachHandlers: function(){
var self = this;
self.items.forEach(function(){
this.addEventListener("mouseover",self.mouseOverHandler,false);
});
}
,mouseOverHandler: function(event){
console.log(this);
}
};
window.onload = function()
{
myObject.attachHandlers();
}
Running this on chrome, When mouseOverHandler
is called, it prints:
Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
I wonder, is addEventListener
changing my context to the window
object? Why so?
I want the event handler added to each element I'm iterating over.
Upvotes: 0
Views: 39
Reputation: 1075367
The reason relates to this line:
this.addEventListener("mouseover",self.mouseOverHandler,false);
In that line, this
is the global object (which is available as window
on browsers). That's the nature of how forEach
works: Unless you specify a thisArg
as the second argument to forEach
(after the function), it uses undefined
. In loose mode, that means that during the call to the iteration function, this
is the global object. (In strict mode, it would mean this
was undefined
.)
If you meant to attach it to each element in the loop, then:
// Accept the arg here ------v
self.items.forEach(function (element) {
element.addEventListener("mouseover", self.mouseOverHandler, false);
// ^--- use it here
});
Then, this
within mouseOverHandler
would refer to the element, because that's a guarantee that addEventListener
gives you. It would not refer to myObject
. If you wanted it to refer to myObject
object instead (although there's no reason to in this case), you might use Function#bind
:
,attachHandlers: function(){
var boundHandler = this.mouseOverHandler.bind(this);
this.items.forEach(function(element){
element.addEventListener("mouseover",boundHandler,false);
});
}
Now, within mouseOverHandler
, this
would refer to your myObject
object (although again, in this case, probably no reason to do that).
More (on my blog):
Side note: In your quoted code, you had addEventListner
(missing e
) rather than addEventListener
, I've corrected it in the examples above.
Upvotes: 1
Reputation: 318332
It's not jQuery, this
inside Array.forEach
is not what you think it is, it's the global Window, while the first argument would be the currently iterated element
self.items.forEach(function (elem) {
elem.addEventListener("mouseover", self.mouseOverHandler, false);
});
Also, you can pass in this
directly as an argument to forEach
and avoid the variable like this
attachHandlers: function () {
this.items.forEach(function (elem) {
elem.addEventListener("mouseover", this.mouseOverHandler, false);
}, this);
},
Upvotes: 1