jQuery:如何在事件处理程序函数中获取事件对象而无需将其作为参数传递?

72

我在链接上有一个 onclick 属性:

<a href="#" onclick="myFunc(1,2,3)">click</a>

这指向JavaScript中的此事件处理程序:

function myFunc(p1,p2,p3) {
    //need to refer to the current event object:
    alert(evt.type);        
}

由于事件对象“evt”未传递给任何参数,是否仍然可以获取此对象?

我尝试使用window.event$(window.event),但两者都是undefined

有任何想法吗?

4个回答

100

由于事件对象“evt”未从参数中传递,是否仍然可以获取此对象?

不可靠。IE和部分其他浏览器会将其作为window.event(而非$(window.event))提供,但这是非标准的,并且并非所有浏览器都支持(著名的例子是Firefox不支持)。

最好将事件对象传递到函数中:

<a href="#" onclick="myFunc(event, 1,2,3)">click</a>

即使在非IE浏览器上也可以工作,因为它们在具有event变量的上下文中执行代码(并且在IE上工作是因为event解析为window.event)。我已经在IE6+,Firefox,Chrome,Safari和Opera浏览器中尝试过。示例:http://jsbin.com/iwifu4

但你最好使用现代事件处理方法:

HTML:

<a href="#">click</a>

使用jQuery的JavaScript代码(因为您正在使用jQuery):

$("selector_for_the_anchor").click(function(event) {
    // Call `myFunc`
    myFunc(1, 2, 3);

    // Use `event` here at the event handler level, for instance
    event.stopPropagation();
});

或者如果你真的想将 event 传递给 myFunc

$("selector_for_the_anchor").click(function(event) {
    myFunc(event, 1, 2, 3);
});
选择器可以是任何标识锚点的内容。您有非常丰富的选择(几乎包含CSS3的全部,还有一些其他的)。您可以为锚点添加idclass,但同样,您还有其他选择。如果您可以使用它在文档中的位置而不是添加人为的内容,那就太好了。

5
谢谢这个解释,JavaScript的这部分一直让我感到困惑。这个无形的神秘“事件”参数从何而来的概念从未被很好地向我解释过。 - Captain Hypertext

15

在IE中可以通过window.event获取事件对象,在其他没有启用'use strict'指令的浏览器中,可以通过arguments.callee.caller.arguments[0]获取事件对象。

function myFunc(p1, p2, p3) {
    var evt = window.event || arguments.callee.caller.arguments[0];
}

1
arguments.callee.caller.arguments 仍然期望事件作为参数/参数传递。 - Caspar Kleijne
1
我在 Chrome 上测试过,它可以正常工作。Event 对象是 HTML 内联事件的隐式参数,而 arguments.callee.caller 是由 HTML 生成的匿名事件处理程序函数,其第一个参数是隐式的 Event 对象。 - otakustay
6
arguments.callee.caller 并不是普遍支持的,有些实现中它的性能非常慢,这是个真正糟糕的想法,在严格模式下是被禁止的。 - T.J. Crowder
1
正确地说,callee和caller虽然可以访问内部函数对象,但不建议使用。但是在事件处理代码与HTML内联放置时,使用该方法是访问Event对象的唯一方式。最好的方法始终是使用JavaScript非侵入式地注册事件 :) - otakustay
无论如何,这都是极其粗糙的。 - John Dvorak
显示剩余7条评论

4

请按照以下方式编写事件处理程序声明:

<a href="#" onclick="myFunc(event,1,2,3)">click</a>

然后你的"myFunc()"函数就可以访问事件了。

"onclick"属性的字符串值会以几乎与浏览器(内部)调用Function构造函数相同的方式转换为函数:

theAnchor.onclick = new Function("event", theOnclickString);

(除IE外)。但是,由于“event”在IE中是全局变量(它是窗口属性),因此您可以在任何浏览器中通过这种方式将其传递给函数。


测试在 Firefox 中,你是对的,它彻底失败了。在贴子遭到大量踩之前将其删除。谢谢你的提醒 :) - JohnP

1
如果您现在像这样在标记上调用事件处理程序,就无法跨浏览器实现。但是,如果使用jQuery绑定单击事件,则可以按照以下方式实现:
标记:
  <a href="#" id="link1" >click</a>

Javascript:

  $(document).ready(function(){
      $("#link1").click(clickWithEvent);  //Bind the click event to the link
  });
  function clickWithEvent(evt){
     myFunc('p1', 'p2', 'p3');
     function myFunc(p1,p2,p3){  //Defined as local function, but has access to evt
        alert(evt.type);        
     }
  }

由于事件对象


1
"如果你像现在这样在标记上调用事件处理程序,你就不能(跨浏览器)。" 实际上,你可以(看我的答案;它适用于所有主要浏览器和我尝试过的所有次要浏览器--IE6+,Firefox,Chrome,Safari,Opera...)。但最好不要这样做。 - T.J. Crowder
但是在你的解决方案中,你将“event”作为参数发送,而LazNiko的要求是不这样做。肯定有另一种方法,但很遗憾,提问者已经离开了:S - Edgar Villegas Alvarado
一种方法(使用标记)确实是从标记中调用clickWithEvent函数,但是我们知道,从标记中调用并不是最好的方式(最终解决方案也是相同的)。 - Edgar Villegas Alvarado

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