Не получается обратиться к методу класса изнутри другого метода

Проблемные места отмечены ! в коде.

{
  "use strict";
  const field = document.querySelector('.wrapper'),
    startGame = document.querySelector('#startGame');

  class TicTacToe {
    constructor() {
      this._started = false;
      this._ended = false;
      this._count = 0;
    }

    start(ev) {
      ev.stopPropagation();
      this._started = true;
      const createField = document.createElement('table');
      createField.classList.add('tic-tac-toe');
      for (let i = 0; i < 3; i++) {
        const tr = document.createElement('tr');
        for (let i = 0; i < 3; i++) {
          const td = document.createElement('td');
          tr.appendChild(td);
        }
        createField.appendChild(tr);
      }
      createField.querySelectorAll('td').forEach((el, i) => {
        el.classList.add(`tdField-${i + 1}`);
      });
      createField.addEventListener('click', this.move, {
        capture: true
      }); //                                ! Вешаю event listener на поле
      field.innerHTML = '';
      field.appendChild(createField);

      this.move(); //                      !!! Если просто обратиться к методу move, то выдаёт ошибку
    }

    move(ev) {
      ev.stopPropagation();
      this._count++;
      this._checkCount();
      if (this.ended) {
        this._end();
      } else {
        this._checkClassList(ev);
      }

      console.log(3); //                     !! При клике должно выводиться 3, но не выводится
    }

    _checkCount() {
      if (this.count >= 9) {
        this._ended = true;
      }
    }

    _checkClassList(evCb) {
      console.log(evCb.target)
    }

    get started() {
      return this._started;
    }

    get count() {
      return this._count;
    }

    get ended() {
      return this._ended;
    }
  }

  const game = new TicTacToe();

  startGame.addEventListener('click', game.start, {
    capture: true
  });
}
.wrapper {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.tic-tac-toe {
  border-collapse: collapse;
}

.tic-tac-toe td {
  border: 2px solid rgb(26, 26, 26);
  width: 100px;
  height: 100px;
  text-align: center;
  cursor: pointer;
}
<div class="wrapper">
  <button id="startGame">Начать!</button>
</div>


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

Автор решения: nörbörnën

const game = new TicTacToe();

startGame.addEventListener('click', game.start, {capture: true});

//

createField.addEventListener('click', this.move, {capture: true});

Вот эти фокусы называются потерей контекста.

Тебе нужно прочитать классический ответ @Grundy и в дальнейшем относиться к контекстам внимательнее.

Работающий код:

const field = document.querySelector('.wrapper'),
  startGame = document.querySelector('#startGame');

class TicTacToe {
  constructor() {
    this._started = false;
    this._ended = false;
    this._count = 0;
  }

  start(ev) {
    ev.stopPropagation();
    this._started = true;
    const createField = document.createElement('table');
    createField.classList.add('tic-tac-toe');
    for (let i = 0; i < 3; i++) {
      const tr = document.createElement('tr');
      for (let i = 0; i < 3; i++) {
        const td = document.createElement('td');
        tr.appendChild(td);
      }
      createField.appendChild(tr);
    }
    createField.querySelectorAll('td').forEach((el, i) => {
      el.classList.add(`tdField-${i + 1}`);
    });
    createField.addEventListener('click', this.move.bind(this), {
      capture: true
    }); //                                ! Вешаю event listener на поле
    field.innerHTML = '';
    field.appendChild(createField);

    this.move(ev); //                      !!! Если просто обратиться к методу move, то выдаёт ошибку
  }

  move(ev) {
    ev.stopPropagation();
    this._count++;
    this._checkCount();
    if (this.ended) {
      this._end();
    } else {
      this._checkClassList(ev);
    }

    console.log(3); //                     !! При клике должно выводиться 3, но не выводится
  }
  
  _end() {
    alert('finita');
  }

  _checkCount() {
    if (this.count >= 9) {
      this._ended = true;
    }
  }

  _checkClassList(evCb) {
    console.log(evCb.target)
  }

  get started() {
    return this._started;
  }

  get count() {
    return this._count;
  }

  get ended() {
    return this._ended;
  }
}

const game = new TicTacToe();

startGame.addEventListener('click', game.start.bind(game), {
  capture: true
});
.wrapper {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.tic-tac-toe {
  border-collapse: collapse;
}

.tic-tac-toe td {
  border: 2px solid rgb(26, 26, 26);
  width: 100px;
  height: 100px;
  text-align: center;
  cursor: pointer;
}
<div class="wrapper">
  <button id="startGame">Начать!</button>
</div>

→ Ссылка