К сожалению, вы не можете рассчитывать на то, что addEventListener
будет настоящей функцией Javascript. (Это верно для некоторых других функций, предоставляемых хостом, например window.alert
). Многие браузеры делают правильную вещь (tm) и делают их истинными функциями Javascript, но некоторые браузеры этого не делают (я смотрю на вас, Microsoft). И если это не настоящая функция 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
. (Обратите внимание, что IE до IE8 не имеет 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
, когда вызывали его; это уже встроено в функцию, потому что функция является замыканием. Если вы не знакомы с ними, моя запись в блоге Закрытия не сложны могут быть полезны.
Вот полный пример:
<!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
будет в вызове функции.
- Принимает аргументы, переданные функции в виде массива (или любой подобной массиву вещи).
Как вы, наверное, знаете, this
в Javascript сильно отличается от this
в некоторых других языках, таких как C ++, Java или C #. this
в Javascript не имеет ничего общего с тем, где определена функция, она полностью определяется тем, как функция называется . Вы должны установить this
на правильное значение каждый раз, когда вызываете функцию. (Подробнее о this
в Javascript здесь .) Есть два способа сделать это:
- путем вызова функции через свойство объекта; который устанавливает
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.