2010-05-23 6 views
2

Я пытаюсь вызвать addEventListener() с помощью метода apply(). Код выглядит так:addEventListener using apply()

 
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); 

Нужна помощь!

Спасибо!

ответ

8

Вы не можете рассчитывать на addEventListener, являющийся настоящей функцией Javascript, к сожалению. (Это справедливо для нескольких других функций, предоставляемых хостом, таких как window.alert). Многие браузеры делают Right Thing (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, когда мы назвали его; он уже встроен в функцию, потому что функция является закрытием. Если вы не знакомы с ними, может оказаться полезным мое сообщение в блоге 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() VS. func(), я думаю, вы, вероятно, уже понял, это просто, что мой первоначальный неправильный ответ спутать вопросы. Но на всякий случай: функции apply вызовов, делая две специальные вещи:

  1. Устанавливает, что this будет в вызове функции.
  2. Принимает аргументы для предоставления функции как массива (или любой подобной массиву вещи).

Как вы, наверное, знаете, this в JavaScript, довольно сильно отличается от this в некоторых других языках, таких как C++, Java или C#. this в Javascript не имеет ничего общего с тем, где определена функция, она полностью определяется тем, как функция называется.Вы должны установить this на правильное значение каждый раз, когда вы вызываете функцию. (Подробнее о в Javascript herethis.) Есть два способа сделать это:

  • путем вызова функции через свойство объекта; который устанавливает 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 т o foo, и переходя в аргументы 1, 2 и 3.

+0

Возможно, я не могу написать подпись addEvetnListener, поскольку это может произойти во время выполнения. Есть ли обходной путь? – Paul

+0

@Paul: 'addEventListener' имеет определенную, определенную подпись. Для реальных функций * Javascript * в общем случае вы можете делать то, что делали. Просто эти неприятные функции, предоставляемые хостом, которые не могут быть «реальными», что вам нужно работать, и у них будут определенные подписи. –

+0

@ Crowder, Извините, я либо неправильно понял, либо оговорюсь ... Я попытался сказать, что, учитывая ваш примерный код, как узнать элемент? (Я использую Firefox.) Также, что отличает fun.apply() и func() (т. Е. Какая разница между вашим кодом и кодом)? Благодаря! – Paul

 Смежные вопросы

  • Нет связанных вопросов^_^