Не получается обратиться к методу класса изнутри другого метода
Проблемные места отмечены ! в коде.
{
"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>