это ключевое слово внутри обратного вызова addEventListener - PullRequest
0 голосов
/ 25 августа 2018

Я прочитал какой-то другой ответ по этой теме, но я не уверен, что понимаю, как ключевое слово this работает внутри addEventListener.

const button = document.querySelector('button');

function foo() { console.log(this) }

button.addEventListener('click', foo);

foo - это обычная функция внутри addEventListener, это не метод для button объекта. Когда вызывается foo, он должен выполняться в контексте глобального объекта, поэтому this должно быть равно window, а не button.

Похоже на ситуацию, подобную этому примеру :

const obj = {
  method: function (cb) {
    console.log('method', this); // `this` === `obj`

    return cb();
  }
};

obj.method(function() {
  console.log('cb', this); // `this` === `window`
});

Где obj может рассматриваться как button, method может быть addEventListener и cb обратным вызовом внутри addEventListener.

Я знаю, что могу использовать bind для изменения контекста this, но я хочу глубже понять, почему он так работает.

Почему this внутри addEventListener обратного вызова вызывается в контексте текущего элемента вместо глобального объекта?

Ответы [ 4 ]

0 голосов
/ 25 августа 2018

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

    function testCallBack(fn){
       console.log('inside testCallBack');
       fn('Hello I am a callBack')
    }

    testCallBack(foo);

    function foo(param){
      console.log(param);
    }

// Outputs: 
inside testCallBack
Hello I am a callBack

Каждая область в JavaScript имеет this объект, который представляетвызывающий объект для функции.
Именно поэтому this внутри обратного вызова addEventListener вызывается в контексте текущего элемента, а не в глобальном объекте.Ниже приведен код для более ясного понимания:

   function sayNameForAll() {
        console.log(this.name);
    }

    var person1 = {
        name: "Rajat",
        sayName: sayNameForAll
    };

    var person2 = {
        name: "pldg",
        sayName: sayNameForAll
    };

    var name = "Sidd";

    person1.sayName();      // outputs "Rajat" here calling object is person1, so this represents person 1
    person2.sayName();      // outputs "pldg"

    sayNameForAll();        // outputs "Sidd"

Поэтому, когда вы вызываете button.addEventListner('click',foo), ваш вызывающий объект - button.

0 голосов
/ 25 августа 2018

Если мы используем функции, которые были определены с использованием ключевого слова function в качестве обработчика событий, то эта функция обработчика событий выполняется в контексте элемента, для которого было привязано событие

button.addEventListener('click', foo);

так, в этом случае значение this внутри foo будет button элементом.

Если вместо них мы используем функции стрелок, то значение this будет объектом окна

Причина в том, что this в функции стрелки имеет то же значение, что и контекст, в котором была создана функция стрелки

button.addEventListener('click', () => { console.log(this) // window } );

Подробнее о лексическом Что такое лексическое «это»?

0 голосов
/ 25 августа 2018

Точно так же, как вы можете использовать bind или call для установки this на то, что вам нужно, API-интерфейсы браузера также могут вызывать ваши функции с любым значением, установленным на this. Он используется множеством странных способов и не очень последовательный. Вне классов и методов this больше похоже на секретный дополнительный аргумент для функции. В этом случае вы можете избежать этого, получив элемент button из event.target.

0 голосов
/ 25 августа 2018

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

Однако при обычном вызове функции не установите this, если выражение вызова не содержит доступа к члену через ..В этих случаях, без "use strict" active, this станет глобальным контекстом, который в браузере равен window.

Если вы хотите, чтобы this для cb было obj,Вы можете заменить cb() на cb.apply(this), что установит cb s this на значение функции включения.

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

...