我正在尝试使用apply()方法调用addEventListener()。代码如下:
function rewrite(old){ return function(){ console.log( 'add something to ' + old.name ); old.apply(this, arguments); } } addEventListener=rewrite(addEventListener);
它不起作用。该代码适用于普通的JavaScript方法,例如
function hello_1(){ console.log("hello world 1!"); } hello_1=rewrite(hello_1);
需要帮助!
谢谢!
答案 0 :(得分:9)
不幸的是,你不能指望addEventListener
是一个真正的Javascript函数。 (对于其他几个主机提供的函数,例如window.alert
)也是如此。许多浏览器都做了正确的事情(tm)并使它们成为真正的Javascript函数,但是有些浏览器没有(我在看你,微软)。如果它不是真正的Javascript函数,它就不会将apply
和call
函数作为属性。
因此,您无法通过主机提供的功能实际执行此操作,因为如果要将代理中的任意数量的参数传递给目标,则需要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 complicated可能会有用。
这是一个完整的例子:
<!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()
与func()
的问题,我想你可能已经明白了,只是我原来的错误答案让人感到困惑。但为了以防万一:apply
调用函数,做两件特别的事情:
this
。您可能知道,Javascript中的this
与其他语言(如C ++,Java或C#)中的this
完全不同。 Javascript中的this
与定义函数的位置无关,它完全由函数调用的方式设置。每次调用函数时,都必须将this
设置为正确的值。 (有关here中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。