Javascript: поведение функции Bind / Unbind - PullRequest
0 голосов
/ 27 ноября 2018

Когда я связываю функцию с родительским this, переданным в thisArg, я не могу отсоединить одноименное выражение функции, но без него я могу отсоединить саму функцию.Почему это так?

Это работает:

choicesList.addEventListener("click", function() {

    const self= this;

    document.addEventListener("click", function checkClick(e) {

        if (!e) e = event;
        if (!self.contains(e.target)) {

            document.removeEventListener("click", checkClick);
        }
    }, false);
});

Это не так:

choicesList.addEventListener("click", function() {

    document.addEventListener("click", function checkClick(e) {

        if (!e) e = event;
        if (!this.contains(e.target)) {
            document.removeEventListener("click", checkClick);
        }
    }.bind(this), false);
});

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Причина этого заключается в том, что вызов bind() для функции возвращает новый экземпляр этой функции:

function someHandler() {
  alert('hi');
}

const someHandlerBinded = someHandler.bind(document);


// Returns false, seeing as these are different instances of the function
console.log( someHandlerBinded === someHandler );

При установке обработчика событий напрямую через результат bind(), как вы находитесь во втором блоке кода, это приводит к тому, что новый экземпляр этого обработчика функции будетперешел на addEventListener().Это, в свою очередь, означает, что последующая попытка удалить этот обработчик в строке:

document.removeEventListener("click", checkClick);

не удастся, поскольку определенная функция checkClick отличается от фактической функции обработчика, используемой для этого события щелчка(т. е. новый экземпляр функции, возвращаемый из function checkClick(){ ... }.bind())

Один из способов решения этой проблемы может быть следующим:

choicesList.addEventListener("click", function() {

    // Declare the bound version of the click handler
    const boundClickHandler = function checkClick(e) {

        if (!e) e = event;

        if (!this.contains(e.target)) {

            // Removing the result of bind, rather than the declared 
            // checkClick handler
            document.removeEventListener("click", boundClickHandler);
        }
    }.bind(this)

    // Adding the result of bind as you currently are doing
    document.addEventListener("click", boundClickHandler, false);
});
0 голосов
/ 27 ноября 2018

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

Вы можете прочитать больше о волатильности this здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...