this с использованием addEventListener

Так alert работает:

class Test {
    #shown;

    constructor() {
        this.#shown = 'hello';
        this.showMessage.bind(this);
    }

    showMessage() {
        alert(this.#shown);
    }
}

var test = new Test;
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div class="container">
            <button class="element" onclick="test.showMessage();">кнопка</button>
        </div>
        <script src="test.js"></script>
    </body>
</html>

А так alert не работает:

class Test {
    #shown;

    constructor() {
        this.#shown = 'hello';
        this.showMessage.bind(this);
    }

    showMessage() {
        alert(this.#shown);
    }
}

var test = new Test;

document.addEventListener('DOMContentLoaded', function() {
    let element = this.querySelector('.element');
    element.addEventListener('click', test.showMessage);
})
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div class="container">
            <button class="element">кнопка</button>
        </div>
        <script src="test.js"></script>
    </body>
</html>

Почему во втором случае alert() не страбатывает, если в обоих случаях я привязываю событие на один и тот же элемент и в обоих случаях использую bind() чтобы this всегда было в контексте класса Test?


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

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

Во 2м примере проблемы связаны с контекстом, в функции, используемой в addEventListener, это не объект test, а кнопка element, у которой нужных методов и свойств нет.

Решить можно, например, такими 2мя способами:

В конструкторе так привязать контекст к функции:

this.showMessage = this.showMessage.bind(this);

Или как в комментарии к вопросу - измените функцию на стрелочную, которая использует контекст выше:

element.addEventListener('click', () => { test.showMessage() });

class Test {
    constructor() {
        this.shown = 'hello';
        this.showMessage = this.showMessage.bind(this);
    }

    showMessage() {
        alert(this.shown);
    }
}

var test = new Test;

document.addEventListener('DOMContentLoaded', function() {
    let element = this.querySelector('.element');
    element.addEventListener('click', test.showMessage);
})
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div class="container">
            <button class="element">кнопка</button>
        </div>
        <script src="test.js"></script>
    </body>
</html>

→ Ссылка