@ewb

Поведение addEventListener отличается при анонимной и именованной функции?

Здравствуйте. Если соберетесь отвечать, то прочитайте пожалуйста текст полностью. Вопрос не в поиске решения, а в правильности понимания работы некоторых моментов js.

Проще всего будет показать на примере какого-то кода.

Например, есть объект, который управляет всплывающим окном с кнопкой.
function Popup() {
      this.btn = document.querySelector("#popup .btn");

      this.btnHandler = function() {
        console.log("из объекта");
      }

      this.btn.addEventListener("click", this.btnHandler);
    }


После создания объекта, в зависимости от потребности мы хотим свободно переопределять обработчик клика по кнопке в окне.

var pup = new Popup();
    
pup.btnHandler = function() {
      console.log("вне объекта");
}


По моей наивности это было вроде логично.
Есть переменная, которая хранит функцию для вызова.
При активации события, дергается переменная указанная в addEventListener и отрабатывает нужная функция хранящаяся в ней.
Но это не работает, все равно выводиться "из объекта".

Поразмыслив немного, я вроде бы понял в чем дело и хочу удостовериться все ли так (поиск мне не выдал точного ответа).
Во первых addEventListener принимает не что-то, а функцию, в данном случае анонимную функцию.
А во вторых this.btnHandler просто переменная, которая что-то хранит (в данном случае функцию), а не функция сама по себе, то есть не имя функции.
То есть когда отрабатывает код
this.btn.addEventListener("click", this.btnHandler);

this.btnHandler просто вернет эту анонимную функцию, а это равносильно
this.btn.addEventListener("click", function() {
      console.log("из объекта");
});


Следовательно addEventListener запомнит только эту анонимную функцию и будет вызывать только ее при активации события. При этом эта функция будет отдельно висеть в памяти?
  • Вопрос задан
  • 487 просмотров
Решения вопроса 2
profesor08
@profesor08 Куратор тега JavaScript
Анонимная функция где-то там регистрируется, ссылка на нее есть в объекте, и эту же ссылку ты передаешь в addEventListener. Когда ты создаешь объект, и задаешь переменной новую функцию, то эта функция тоже регистрируется и ссылка на нее устанавливается этой переменной. Но, в eventListner ссылка не будет переназначена. Решить можно разными способами, первое что приходит в голову это удалять старый слушатель и устанавливать новый. Либо задать один какой-то слушатель, который будет вызывать некий код, который будет уже выполнять нужные тебе действия.
function Popup() {
  this.btn = document.querySelector("h1");

  this.btnHandler = e => console.log(e);

  this.btn.addEventListener("click", e => this.btnHandler(e));
}

let p = new Popup();

p.btnHandler = e => console.log(111);
Ответ написан
Комментировать
Stalker_RED
@Stalker_RED
Есть переменная, которая хранит функцию для вызова.
Вот здесь первое заблуждение. Не хранит она функцию. В переменной ссылка (указатель) на функцию, и таких ссылок-переменных может быть несколько. И когда вы делаете pup.btnHandler = function() ..., то переменная теперь указывает на другую функцию, но старая функция, которая уже привязана - никуда не исчезает.

Если надо менять - можно так:

Кривовато выглядит, потому что подгонял под ваш код, чтоб понятнее.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
AngReload
@AngReload
Кратко о себе
Правильно понимаешь.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы