Почему не удаляет обработчик

var func = {
    options: {
        'root': null
    },
    move: function(event) {
        event.preventDefault();
        console.log('move');
    },
    down: function(event) {
        event.preventDefault();
        console.log('down');
        this.options.root.addEventListener('mousemove', this.move.bind(this), false);
    },
    up: function() {
        console.log('up');
        this.options.root.removeEventListener('mousemove', this.move.bind(this), false);
    },
    init: function() {
        console.log('init');
        this.options.root = document.getElementById('button');
        this.options.root.addEventListener('mouseup', this.up.bind(this), false);
        this.options.root.addEventListener('mousedown', this.down.bind(this), false);
    }
}

func.init();
<button id="button">button</button>

Почему после отпускания мышки, не удаляется обработчик 'move'?


Ответы (1 шт):

Автор решения: eccs0103

Причина

Каждый вызов Function.bind() это отдельная копия той же функции и эти копии РАЗНЫЕ, то есть:

function foo() {}
const a = foo.bind();
const b = foo.bind();
console.log(a == b); // false

Вот и метод removeEventListener не находит вашу первоначальную копию от bind, чтобы удалить.

Решение

Тогда что можно делать? Не надо bind-овать каждый раз, сохраните ссылку на копию и удалите:

var func = {
  options: {
    'root': null
  },
  move: function(event) {
    event.preventDefault();
    console.log('move');
  },
  moveCopy: undefined,
  down: function(event) {
    event.preventDefault();
    console.log('down');
    this.moveCopy = this.move.bind(this);
    this.options.root.addEventListener('mousemove', this.moveCopy, false);
  },
  up: function() {
    console.log('up');
    this.options.root.removeEventListener('mousemove', this.moveCopy, false);
  },
  init: function() {
    console.log('init');
    this.options.root = document.getElementById('button');
    this.options.root.addEventListener('mouseup', this.up.bind(this), false);
    this.options.root.addEventListener('mousedown', this.down.bind(this), false);
  }
}

func.init();
<button id="button">button</button>

→ Ссылка