Давайте разберем этот шаг за шагом.
Общая информация
Функция / метод .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);
});