Polymer 2.0: зачем нужна анонимная функция при императивном добавлении слушателя

В новой документации для Polymer 2.0 (https://www.polymer-project.org/2.0/docs/devguide/events#imperative-listeners), он дает следующий пример:

ready() {
  super.ready();
  this.addEventListener('click', e => this._myClickListener(e));
}

добавить прослушиватель событий в обязательном порядке. Если вы хотите удалить слушателя, нам нужно будет сделать следующее (согласно документам):

constructor() {
  super();
  this._boundListener = this._myLocationListener.bind(this);
}

connectedCallback() {
  super.connectedCallback();
  window.addEventListener('hashchange', this._boundListener);
}

disconnectedCallback() {
  super.disconnectedCallback();
  window.removeEventListener('hashchange', this._boundListener);
}

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

Однако, почему мы должны использовать .bind(this)? Я понимаю, что он возвращает новую функцию, которая привязывает функцию к тому, чем является «это», поэтому полезно создать новую ссылку на сохраненную функцию, чтобы мы могли добавлять и удалять одну и ту же ссылку на функцию.

Но почему мы не можем сделать это с первым примером? Разве this._myClickListener(e) в первом сегменте кода также не имеет уникальной ссылки на функцию, которая не меняется, на которую мы можем ссылаться для добавления и удаления прослушивателя? Зачем нам вообще нужно оборачивать его в анонимную функцию? Я чувствую, что это решило бы проблему, которая была подробно решена во втором сегменте кода, но это явно сделано не просто так.

Спасибо за любую помощь или предложения заранее!


person Bradass    schedule 14.08.2017    source источник


Ответы (2)


Если вы передадите this._myClickListener в качестве обратного вызова, то он не будет вызываться с нужным вам значением this, поскольку именно реализация DOM запускает вызов к нему, и он не будет знать о вашем this: this будет просто глобальным объект (или undefined в строгом режиме).

Тогда вы могли бы сказать: ОК, я привяжу к ней this с помощью this._myClickListener.bind(this), но теперь у вас нет ссылки на эту функцию, которая создается на месте. При попытке вызвать removeEventListener вы не можете получить к нему доступ с помощью this._myClickListener.bind(this), так как это просто снова создает новую функцию, а не ту, которую вы использовали раньше.

Таким образом, нет другого способа, кроме как присвоить связанную функцию переменной и использовать эту переменную как в addEventListener, так и в removeEventListener: это единственный способ удовлетворить два условия одновременно:

  • У вас есть ссылка на функцию
  • Функция привязана к правильному this
person trincot    schedule 14.08.2017

Когда вы передаете метод объекта в качестве параметра функции/методу, он находится вне своего естественного контекста (this не привязан к исходному объекту), поэтому по-прежнему использовать его, как если бы это был обычный вызов метод для этого объекта, вы используете bind, который явно привязывает контекст и возвращает функцию, привязанную к этому контексту.

person Vivick    schedule 14.08.2017