请考虑以下代码:
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();
}
在chrome上运行此命令,当调用mouseOverHandler
时,它会打印:
Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
我想知道,addEventListener
是否将我的上下文更改为window
对象?为什么这样?
我希望将事件处理程序添加到我迭代的每个元素中。
答案 0 :(得分:1)
它不是jQuery,this
里面Array.forEach
不是你想象的那样,它是全局窗口,而第一个参数是当前迭代的元素< / p>
self.items.forEach(function (elem) {
elem.addEventListener("mouseover", self.mouseOverHandler, false);
});
此外,您可以直接将this
作为参数传递给forEach
并避免像这样的变量
attachHandlers: function () {
this.items.forEach(function (elem) {
elem.addEventListener("mouseover", this.mouseOverHandler, false);
}, this);
},
答案 1 :(得分:1)
原因与这一行有关:
this.addEventListener("mouseover",self.mouseOverHandler,false);
在该行中,this
是全局对象(在浏览器上可用作window
)。这就是forEach
工作原理的本质:除非您指定thisArg
作为forEach
的第二个参数(在函数之后),否则它使用undefined
。在松散模式下,这意味着在调用迭代函数期间,this
是全局对象。 (在严格模式下,这意味着this
为undefined
。)
如果您打算将它附加到循环中的每个元素,那么:
// Accept the arg here ------v
self.items.forEach(function (element) {
element.addEventListener("mouseover", self.mouseOverHandler, false);
// ^--- use it here
});
然后,this
中的mouseOverHandler
会引用该元素,因为这是addEventListener
为您提供的保证。它不引用myObject
。如果您希望它引用myObject
对象(尽管在这种情况下没有理由),您可以使用Function#bind
:
,attachHandlers: function(){
var boundHandler = this.mouseOverHandler.bind(this);
this.items.forEach(function(element){
element.addEventListener("mouseover",boundHandler,false);
});
}
现在,在mouseOverHandler
内,this
会引用您的myObject
对象(尽管在这种情况下,可能没有理由这样做)。
更多(在我的博客上):
附注:在您引用的代码中,您有addEventListner
(缺少e
)而不是addEventListener
,我已在上面的示例中对其进行了更正。