Javascript ES6 addEventListener внутри класса

Я изучаю ES6 и не понимаю, почему мой addEventListener не работает (запускается только один раз), когда я использую такую ​​функцию:

// Trigger only one time
window.addEventListener("scroll", this.scroll() );

Но когда я делаю это:

// working !!
window.addEventListener("scroll", (e) => {
    let top = window.pageYOffset;

    console.log(top + " vs " + this.offsetTop)

    if (top >= this.offsetTop) {
        this.el.classList.add('is-sticky');
    } else {
        this.el.classList.remove('is-sticky');
    }

});

Полный код можно найти здесь: https://codepen.io/paallaire/pen/GQLzmg/?editors=0010#0


person Lofka    schedule 04.03.2018    source источник
comment
В foo(bar()) bar всегда вызывается первым, и его возвращаемое значение передается в foo. addEventListener ожидает передачи функции, вы передаете возвращаемое значение this.scroll() (которое не является функцией).   -  person Felix Kling    schedule 04.03.2018


Ответы (1)


Заявление:

window.addEventListener("scroll", this.scroll() );

Привязывает к событию результат this.scroll(), который является вызовом функции. Такой вызов возвращает undefined, потому что метод scroll не имеет инструкции return:

scroll() {
    let top = window.pageYOffset;
    console.log(top + " vs " + this.offsetTop);

    if (top >= this.offsetTop) {
        this.el.classList.add('is-sticky');
    } else {
        this.el.classList.remove('is-sticky');
    }
}

Правильный путь

НЕ используйте:

window.addEventListener("scroll", this.scroll);

Приведенный выше код свяжет this с window при срабатывании события.

ПРАВИЛЬНЫЙ способ использования:

window.addEventListener("scroll", (e) => {
   this.scroll();
});

Or

window.addEventListener("scroll", this.scroll.bind(this));

Который, когда событие инициируется, будет иметь код внутри this.scroll, указывающий this на экземпляр текущего класса (Sticky).


Удаление прослушивателя событий

Чтобы удалить событие, вызовите window.removeEventListener, но есть предостережение: removeEventListener нужно вызывать с тем же аргументом, что и в addEventListener, чтобы удалить прослушиватель. Другими словами, чтобы иметь возможность удалить, вам нужно будет сделать:

// save the function that will be bound to the event, so you can remove it later
this.scrollBoundFunction = this.scroll.bind(this);
window.addEventListener("scroll", this.scrollBoundFunction);

// and later
window.removeEventListener("scroll", this.scrollBoundFunction);
person acdcjunior    schedule 04.03.2018
comment
Спасибо за ответ, но как с помощью этой техники удалить EventListerner? - person Lofka; 04.03.2018
comment
Вы должны позвонить removeEventListener, но есть оговорка, проверьте обновленный ответ. - person acdcjunior; 04.03.2018
comment
Хотя часть об удалении прослушивателя событий работает, мне любопытно, почему это работает в первую очередь. Согласно MDN, function.bind(target) возвращает новую функцию с ее this, установленной на то, что было target. Но при предоставлении this.boundFunction в addEventListener, почему this.boundFunction не страдает от собственного ключевого слова this, которое предваряет его отсутствием привязки? Это какая-то оптимизация JS? - person micka190; 09.12.2020
comment
Хм, я не уверен, что понимаю, что вы имеете в виду, но, насколько я понимаю, bind работает именно для того, чтобы переопределить this, возвращая функцию, у которой this жестко запрограммировано (поскольку ее нельзя снова связать) с bind аргумент. Это полезно? Если нет, можете ли вы перефразировать то, что вы только что сказали? - person acdcjunior; 10.12.2020