addEventListener出现非法调用的类型错误

17

我尝试使用以下两种方式添加事件监听器,但都遇到了“非法调用”的类型错误:(当应该添加监听器时出现错误,而不是在单击目标时)

ronan.addEventListener("click", alert, false);

addEventListener.apply(ronan, ["click", alert, false]);

ronan 是一个 div 元素,控制台可以成功返回它,因此我认为这不是问题所在。你有什么想法,为什么会出现此错误?我阅读了此文,但没有从中找到答案。


1
可能是alert原生函数的问题。一个空白的function(){}能否替代它? - James
@J-P:apply的第一个参数是原型,这就是我理解中apply的重点。 @phihag:调用元素的代码在我的JS中的许多其他地方都成功使用。它很长而且不相关,但当我在控制台输入ronan时,我会得到以下返回值: <div style=​"position:​ relative;​ top:​ 37px;​ left:​ 10px;​ margin-bottom:​ 5px;​ height:​ 37px;​ " id=​"bandRonan Delisle Quartet" class=​"all">​…​</div>​ - Artur Sapek
我指的是我在西雅图的早晨,因为我太困了,几乎无法再考虑这个问题了。 - Artur Sapek
1
你们所有人都错了,关于第二行使用 apply - 应该是 HTMLElement.prototype.addEventListener.apply(ronan, [function () { }]); - Matthew
@Artur Sapek 你没有说是哪个浏览器产生了这个错误。在Internet Explorer 9之前的版本,你必须使用attachEvent而不是addEventListener - Matthew
显示剩余7条评论
1个回答

30
您需要将alert包裹在一个函数中。这样做将会生效:
ronan.addEventListener("click", function() { alert('Hi'); }, false);

这里有一个演示。仅使用 alert 不起作用,因为当监听器被执行时,函数内部的 this 值被设置为正在监听的对象。例如,如果在 ronan 上设置了监听器,则在该监听器内部 this === ronan。这会对 alert 造成问题,因为该函数期望 this 等于 window。您可以通过将函数包装在另一个函数中或将其绑定到它期望的任何对象上来解决这个问题。

document.body.addEventListener('click', alert.bind(window), false);

请注意,在IE <9中,您需要使用attachEvent而不是addEventListener


关于在addEventListener中使用apply/call的说明

您的第二次尝试将无法工作,因为您尝试将参数应用于window.addEventListener,而不是HTMLElement.prototype.addEventListener,这是完全不同的函数:

// This won't work
addEventListener.apply(ronan, ["click", alert.bind(window), false]);

// This will work
HTMLElement.prototype.addEventListener.apply(ronan, ['click', alert.bind(window), false]);

1
哦,没错,你说得对。实际上我甚至没有使用原型对象,只是基础部分,但是你的方法仍然可以在没有原型部分的情况下工作。由于我的JS非常专注于DOM,所以我可能应该知道bind()。非常感谢你的时间! - Artur Sapek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接