Номер телефона

Последнее обновление:

Как передать ВНЕШНИЕ аргументы (параметры) обработчикам событий в javascript

При назначении обработчиков тех или иных событий элементам html при помощи средств языка JS, нередко требуется передавать этим обработчикам те или иные аргументы в виде переменных. Это могут быть такие переменные, которые создаются вне тела обработчика.

Данная задача решается не совсем тривиально. Тут можно применить, скажем, «непосредственную» передачу аргументов, передачу через замыкание и т.д.

Мы рассмотрим 5 разных способов, которые, кажется, наиболее распространены. Чтобы не тратить время на вступление, сразу посмотрим код соответствующего тестового html-файла:

<html>

<body>
<button class="input1">Show parameter1</button>
<button class="input2">Show parameter2</button>
<button class="input3">Show parameter3</button>
<button class="input4">Show parameter4</button>
<button class="input5">Show parameter5</button>

<script>
(function(){
// 1.
   
var input1 = document.querySelector('button.input1');
   input1.addEventListener('click', Func, false);
   input1.Param = '1_method !';

   function Func(e){
       alert(e.target.Param + '\n - target \n'+ this.outerHTML);
       alert(e.currentTarget.Param + ' - currentTarget');
       e.currentTarget.removeEventListener('click', Func, false)
   }

// 2.
var someVar = other_function;
var par = '2_method';
var input2 = document.querySelector('button.input2');
var x;

input2.addEventListener("click", x = function (e){
   some_function(e, par, this);
}, false);

function other_function(par) {
   alert(par + '\n - other_function');
   input2.removeEventListener('click', x, false);
   return 'OK';
}

function some_function(e, par, $this) {
   alert($this.outerHTML);
   alert(someVar(par) + '\n event.type='+e.type+  '\n - some_function');
}

//3.
var x3;
var input3 = document.querySelector('button.input3');
var par3 = '3_method';
input3.addEventListener("click", x3 = some_func.bind(null, null), false);

   function some_func(not_used, e) {
       alert(e.type+ '\n'+ par3 + '\n'+ not_used);
       input3.removeEventListener('click', x3, false);
   }

//4.
var input4 = document.querySelector('button.input4');
var par4 = '4_method';
var par41 = 'Also 4_method';

var func4_enclosure = function(v4, v41, e){
   alert(v4 +'\n'+ v41 + '\n'+ e.type);
};
input4.addEventListener('click', (function(par4, par41){
  return function(e){
      func4_enclosure(par4, par41, e);
      this.removeEventListener(e.type, arguments.callee, false); // Удаляем АНОНИМНЫЙ обработчик!!
 
};
})(par4, par41), false);


//5.
var input5 = document.querySelector('button.input5');
var param5 = '5_method';
function wrapEventCallback(callback){
   var args = Array.prototype.slice.call(arguments, 1);
   return function y(e){
       callback.apply(this, args);
       callback(this.outerHTML); //
       
input5.removeEventListener('click', y, false);
   }
}

var func5 = function(v){
   alert(v);
};
input5.addEventListener('click',wrapEventCallback(func5, param5))
})();

</script>
</body>
</html>


Вы можете скопировать себе этот код и протестировать самостоятельно. Или – понажимайте кнопки прямо на этой странице и проверьте, как передаются аргументы на примере обработчиков кликов по кнопкам.

ВСЕ обработчики будут срабатывать по одному разу, после чего они будут удалены – так сделано лишь в целях демонстрации возможностей. Но, если требуется, чтобы обработчики срабатывали и в дальнейшем, можно убрать из них строчку с removeEventListener().

Далее рассмотрим комментарии по каждому методу, чтобы было понятнее.

1 метод: используем переменную this

Вообще, смысл этой переменной зависит от контекста ее использования. В данном случае, при назначении обработчика, в эту переменную будет записана ссылка на объект (например, соответствующий элементу html, на который назначено событие).

1 метод использует функцию Func, у которой единственным задаваемым аргументом является событие е. Ну, и аргумент this, который передается неявно.

Обратите внимание: имя функции Func следует писать, при назначении обработчика, БЕЗ скобок. В противоположном случае, если Вы напишете Func() или Func(…аргументы…), эту функция выполнится в момент назначения обработчика. Поэтому при нажатии на кнопку обработчик клика срабатывать уже не будет. Дело в том, что наличие скобок после имени функции означает, что она должна быть выполнена. Конечно, это не касается ситуации, когда функция инициализируется, т.е. что-то вроде function Func(…){…}.

А уже функция Func может принимать некие аргументы. Которые могут быть только глобальными – или в целом по скрипту, или, по крайней мере, для этой функции. Например, если объявить некоторые переменные ДО назначения обработчика, они будут доступны его функции. Или же, как сделано в данном примере, можно объявить аргументы через свойство Param, которое присваивается объекту – элементу html (в данном случае – первой кнопке, имеющей класс input1).

Для примера, показана передача лишь одного параметра, но можно передать и массив. Это позволит передать не один, а несколько параметров (аргументов). Протестируйте обработчик, нажав на кнопку:


2 метод: через анонимную функцию

Как видим, конструкция анонимной функции позволяет передавать параметры прямо в нее, в виде аргументов содержащейся внутри не функции (в данном случае, some_function() ). Для примера, помимо «стандартных» e и this передана также переменная par.

Также обратите внимание, что язык JS допускает именование функций по аналогии с именованием переменных (см. переменную someVar, которая получила имя функции other_function). При этом вызов функции someVar() осуществляется точно так же, как и вызов любой другой функции – путем указания скобок (с, возможно, аргументами) после ее имени.

 Т.е. этот способ использует комбинацию средств: переменную this и передачу аргумента внутри функции some_function(), вызванной, в свою очередь, внутри анонимной функции.

Как видим, обработчик, назначенный при помощи анонимной функции, ВПОЛНЕ МОЖЕТ БЫТЬ удален, как только в этом появится необходимость. Это следует взять на заметку.

3 метод: использование bind

Это, на наш взгляд, несколько экзотический метод, с использованием аргументов null. Использование bind также позволяет удалить обработчик, при необходимости. А так, это, по сути, аналог предыдущего метода, только со слегка усложненным синтаксисом.

4 метод: замыкание

Это, можно сказать, красивый и универсальный метод передачи переменных. Правда, для начинающих он может показаться немного сложным… но, как говорится – дорогу осилит идущий. Его просто стоит ПОПРОБОВАТЬ несколько раз в своих проектах, а потом все станет очевидным.

Обратите внимание на характерную конструкцию вида:

(function(…){...})();

Это – «самозамкнутая» функция, в которой все переменные, будучи объявленными, являются локальными для нее.

Внутри этой функции присутствует

return function(e){…}

И вот в эту-то функцию и передается объект события е, в данном случае – событие клика (click).

И, наконец, уже внутри нее вызывается функция func4_enclosure(). А уж в нее могут быть переданы параметры обычными образом, например, объявленные и заданные ранее переменные par4 и par41.

 Обратите внимание на более универсальный способ удаления обработчика события, чем в предыдущих методах:

this.removeEventListener(e.type, arguments.callee, false); // Удаляем АНОНИМНЫЙ обработчик!!

Как видим, здесь все параметры этой команды заданы через переменную this (объект элемента, на который назначено событие) и через свойства события type и callee. Это достаточно малоизвестный способ. Но, вполне рабочий. Позволяет удалить АНОНИМНЫЙ обработчик. Который, если следовать классике, удалить, якобы, «невозможно», так как у анонимной функции неизвестно имя (а для удаления обработчика требуется явное указание имени функции). Но, как видим, анонимный обработчик в данном случае прекрасно удаляется.

5 метод: использование callback-функции

Этот метод тоже может показаться сложным для начинающих. Замечателен он тем, что callback-функция, в отличие от обычной функции. позволяет принимать аргументы и при этом. несмотря на наличие круглых скобок после ее имени, НЕ будет выполнена в момент инициализации обработчика. Например, здесь передается переменная param5, а также имя функции func5, которая (на заметку) работает В ДОПОЛНЕНИЕ к основному обработчику из этого метода.

Посмотрим, что тут происходит, ибо синтаксис callback-функции является, и в самом деле, несколько сложным, особенно для первого раза.

var args = Array.prototype.slice.call(arguments, 1);

Здесь происходит привязывание всех аргументов, полученных функцией wrapEventCallback и преобразование их в массив.

На заметку: если вам потребуется сделать преобразование массивоподобного объекта, например, коллекции в массив – лучше использовать именно этот способ. Удобно и буквально в одну строчку. Особенно это ценно, если вы захотите делать сайты не какие попало (потом – вынуждая пользователь обновлять браузеры), а кроссбраузерные. Потому что данный способ хорошо работает и в старых браузерах тоже; а вот более новые функции, предназначенные для такого преобразования, работают не везде.

Итак, массив args представляет собой массив аргументов, переданных в функцию wrapEventCallback. В данном случае это – значение переменной param5.

Далее используем обычное замыкание, как и в примере 4. Имя функции y используется только для того, чтобы потом можно было удалить обработчик через removeEventListener стандартным способом. Однако, вполне можно применить и способ из метода 4, для удаления анонимного обработчика, тогда можно было бы обойтись без использования имени функции y.

Переменная callback представляет собой содержимое (тело) функции-обработчика – в данном случае, тело функции func5. Если написать после ее имени скобки и передать в нее, в скобках, какой-нибудь аргумент (скажем, this.outerHTML - см. пример), то она выполнится с учетом этого аргумента.

Однако, перед этим следует привязать массив с аргументами к объекту нажатой кнопки, т.е. к ее функции-обработчику. Это делается путем

callback.apply(this, args);

Так что такой вот, немножно «навороченный», но зато универсальный синтаксис.

В заключение

На наш взгляд, приведенных пяти методов более, чем достаточно, для того, чтобы передать внешние аргументы в функцию-обработчик события. Наверное, этих методов хватит, чтобы использовать в каких бы то ни было ситуациях, связанных с необходимостью использования внешних (по отношению к функции-обработчику) переменных. Также мы с вами познакомились с малоизвестным способом удаления обработчика события, заданного анонимной функцией. Напишите, что вы думаете по этому поводу.


Комментарии:
Всего комментариев:0
Пожалуйста, не забудьте ознакомиться с правилами оставления комментариев.



Подписаться на комментарии на этой странице

Мы можем выполнить

Другие услуги
Интересная и полезная
информация
НАПИШИТЕ НАМ
Яндекс.Метрика
Номер телефона
© Copyright Все права защищены 2013-2024 Научный консалтинг