不幸的是,你不能指望addEventListener
成为一个真正的 Javascript 函数。(这适用于其他几个主机提供的功能,例如window.alert
)。许多浏览器做正确的事(tm)并使它们成为真正的 Javascript 函数,但有些浏览器却没有(我在看着你,微软)。如果它不是一个真正的 Javascript 函数,它就不会将apply
andcall
函数作为属性。
因此,您不能真正使用主机提供的函数来执行此操作,因为apply
如果您想将任意数量的参数从代理传递到目标,则需要该功能。相反,您必须使用特定函数来创建知道所涉及的主机函数签名的包装器,如下所示:
// Returns a function that will hook up an event handler to the given
// element.
function proxyAEL(element) {
return function(eventName, handler, phase) {
// This works because this anonymous function is a closure,
// "closing over" the `element` argument
element.addEventListener(eventName, handler, phase);
}
}
当您调用它时,传入一个元素,它会返回一个函数,该函数将通过addEventListener
. (请注意,IE8 之前的 IE 没有addEventListener
,但它使用attachEvent
了。)
不知道这是否适合您的用例(如果不适合,有关用例的更多详细信息会很方便)。
你会像这样使用上面的:
// Get a proxy for the addEventListener function on btnGo
var proxy = proxyAEL(document.getElementById('btnGo'));
// Use it to hook the click event
proxy('click', go, false);
请注意,我们在调用它时没有将元素引用传递proxy
给它;它已经内置在函数中,因为函数是一个闭包。如果您不熟悉它们,我的博客文章Closures are not complex可能会很有用。
这是一个完整的例子:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
#log p {
margin: 0;
padding: 0;
}
</style>
<script type='text/javascript'>
window.onload = pageInit;
function pageInit() {
var proxy;
// Get a proxy for the addEventListener function on btnGo
proxy = proxyAEL(document.getElementById('btnGo'));
// Use it to hook the click event
proxy('click', go, false);
}
// Returns a function that will hook up an event handler to the given
// element.
function proxyAEL(element) {
return function(eventName, handler, phase) {
// This works because this anonymous function is a closure,
// "closing over" the `element` argument
element.addEventListener(eventName, handler, phase);
}
}
function go() {
log('btnGo was clicked!');
}
function log(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.getElementById('log').appendChild(p);
}
</script>
</head>
<body><div>
<input type='button' id='btnGo' value='Go'>
<hr>
<div id='log'></div>
</div></body>
</html>
关于你下面关于func.apply()
vs.的问题func()
,我想你可能已经明白了,只是我原来的错误答案混淆了问题。但以防万一:apply
调用函数,做了两件特殊的事情:
- 设置
this
函数调用中的内容。
- 接受作为数组(或任何类似数组的东西)提供给函数的参数。
您可能知道, Javascript 与其他一些语言(如 C++、Java 或 C# this
)有很大不同。在 Javascript 中与函数的定义位置无关,它完全取决于函数的调用方式。每次调用函数时都必须设置正确的值。(这里有更多关于Javascript的信息。)有两种方法可以做到这一点:this
this
this
this
- 通过对象属性调用函数;设置
this
为调用中的对象。例如,foo.bar()
设置this
为foo
并调用bar
。
- 通过自己的
apply
或call
属性调用函数;那些设置this
为他们的第一个论点。例如,bar.apply(foo)
或bar.call(foo)
将设置this
为foo
并调用bar
。
apply
和之间的唯一区别call
是它们如何接受要传递给目标函数的参数:apply
接受它们作为数组(或类似数组的东西):
bar.apply(foo, [1, 2, 3]);
而call
接受它们作为单独的参数:
bar.apply(foo, 1, 2, 3);
它们都调用bar
、this
设置foo
和传递参数 1、2 和 3。