Слушатели событий с аргументами - PullRequest
0 голосов
/ 23 мая 2019

Я хочу передать аргументы слушателю событий в Javascript. Я нашел решения, но не могу понять, почему или как они работают, и почему другие решения не работают.

У меня есть фон C / C ++, однако в Javascript функции выполняются очень по-разному. Не могли бы вы помочь мне понять, как и почему следующие примеры работают или не работают?

Без параметров код работает нормально:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction);

function eventFunction()
{
  console.log("works");
}

Если я включаю скобки в eventListener, функция выполняется один раз без запуска события, а затем ничего не делает:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction());

function eventFunction()
{
  console.log("works");
}

Я полагаю, это потому, что функция вызывается в eventListener, и это не позволяет функции eventListener позднее вызывать функцию eventFunction.


Когда я хочу передать аргумент с помощью eventFunction. Следующее не работает:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction("works"));

function eventFunction(myStr)
{
    console.log(myStr);
}

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


Чтобы правильно передать аргумент в функции события, я нашел следующий код. Следующее решение отлично работает:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction("works"));

function eventFunction(myStr)
{
  function func(event, myStr)
  {
    console.log(myStr);
  }

  return function(event) { 
    func(event,myStr) 
  };
}

Первое, что я заметил, это то, что эта функция не вызывается сразу. Почему это так?

Однако я не знаю, как аргументы передаются внутри каждой функции. Я понимаю, что литерал "works" передается myStr в функцию eventFunction. Однако в функции func есть дополнительный параметр события, который не передается функцией eventFunction.

Кроме того, почему eventFunction должна возвращать другую функцию с одним параметром, который внутренне вызывает функцию func?

Также обратите внимание, что я хочу передать параметры в функцию EventFunction, которые не имеют глобальной области видимости, иначе не было бы необходимости передавать параметры.

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Давайте разберем этот шаг за шагом.

Общая информация

Функция / метод .addEventListener принимает 2 (или 3) аргумента:

  • a String, со значением типа / имени события (например, "click")
  • указатель на Function, который должен выполняться при возникновении события
  • a Boolean, указывающий, следует ли использовать всплывающее или распространяющееся событие.Этот аргумент является необязательным и может быть опущен.

Пример 1

В первом примере вы передаете String ("click") и a указатель на a Function (eventFunction) на .addEventListener.Все работает, как ожидалось, событие происходит, и функция выполняется.

Пример 2

В этом примере вы передаете String и undefined в .addEventListener, а это не то, что .addEventListener ожидает.Вы можете спросить себя: « Когда я прошел undefined? ».Что ж, это случилось, как только вы казнили свой eventFunction, добавив после него парены ().Здесь синтаксис в JS равен синтаксису в большинстве других языков, добавление символов в правой части функции выполняет функцию.

Поскольку ваш eventFunction ничего не возвращает явно, он автоматически возвращаетundefined.Поэтому .addEventListener получил:

clicker.addEventListener("click", undefined)

Однако, поскольку вы выполнили eventFunction, он "It worked" записывает на консоль один раз .

Пример 3

В этом примере произошел сбой по тем же причинам, что и для примера 2.

Пример 4

Код в последнемПример работает, потому что он использует концепцию, называемую закрытием.Есть буквально тысячи объяснений концепции, поэтому мое объяснение здесь будет очень коротким.Если у вас возникли проблемы с его пониманием, просто найдите в Google «javascript closures».

В отличие от многих других языков, JavaScript имеет функция scoping вместо block scoping ,Таким образом, если вы определяете переменную внутри функции F и возвращаете другую функцию G из F, G будет иметь доступ к переменным и аргументам из внутри F.Для демонстрационных целей:

function F () {
  var fVariable = 'Defined in F';
  return function G () {
    return fVariable; // <-- this is the closure
  }
}

var funcG = F(); // <-- execute F
funcG(); // -> 'Defined in F';

Сравните этот короткий пример с вашим четвертым кодом: они практически одинаковы.Единственное отличие состоит в том, что ваш код создает дополнительную функцию func.

Теперь, если вы вызываете clicker.addEventListener("click", eventFunction("it works")), вы выполняете eventFunction, которая возвращает другую (анонимную / лямбда) функцию, которая инкапсулирует "it works" строка через замыкание.Если мы напишем это от руки, вот что .addEventListener «видит»:

clicker.addEventListener("click", function (event) {
  func("it works", event);
});

РЕДАКТИРОВАТЬ: решение проблемы

Вот рабочий пример, обратите вниманиечто я изменил имена функций, чтобы отразить их назначение:

function eventHandlerFactory (myStr) { // <-- eventFunction in your code
  return function executeOnEvent (event) { // <-- executed if an event occurs
    console.log(myStr);
    console.log(event);
  }
}

clicker.addEventListener("click", eventHandlerFactory("it worked"));

Функция eventHandlerFactory возвращает функцию executeOnEvent, которая передается в .addEventListener.Записав это снова, вот что понимает переводчик:

clicker.addEventListener("click", function executeOnEvent (event) {
  console.log("it works");
  console.log(event);
});
0 голосов
/ 23 мая 2019

Первое, что я замечаю, это то, что эта eventFunction не вызывается немедленно

Она вызывается немедленно.Тем не менее, он возвращает новую функцию.Эта функция зарегистрирована для обработчика кликов.При вызове эта функция вызывает функцию func в замыкании.Аргументы, передаваемые этой функции, также сохраняются в замыкании.

Чтобы понять эту концепцию, необходимо понять, как работают замыкания.Об этой теме много писали, поэтому я просто укажу на Как работают замыкания JavaScript? .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...