Проблема с контекстом и this
Здравствуйте!
Решил осваивать и переходить на ООП и вот бывает, что встречаются головоломки. Это полностью рабочий скрипт, но в функции "goAction(e)" this указывает на элемент DOM, а не на объект game. И не получается использовать this. Я пробовал сохранять и передавать контекст, ничего не помогает. Пробовал такие варианты: var they = this; this.they = this; nextGamer.call(this); И еще кучу вариантов. Из-за этого приходится явно указывать название объекта - "game.". Хотя тут нужно использовать this. goAction(e){ var e = e.target; if(game.nextGamer == 'X'){ e.innerHTML = 'X'; game.nextGamer = 'O'; } else { e.innerHTML = 'O'; game.nextGamer = 'X'; } game.checkWins(); } Что скажите вообще? <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Game</title> </head> <body> <div id="wrapper"> <div class="btn"></div><div class="btn"></div><div class="btn"></div> <div class="btn"></div><div class="btn"></div><div class="btn"></div> <div class="btn"></div><div class="btn"></div><div class="btn"></div> </div> <script> class Game { constructor(){ this.nextGamer = 'X'; // запоминаем, чей ход this.gameCell = document.querySelectorAll('#wrapper .btn'); // получаем клетки игрового поля this.winsCombinations = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6],[1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]; // Выигрышные комбинации } // навешиваем функцию goAction на клетки игрового поля on (){ for(var i = 0; i < this.gameCell.length; i++){ this.gameCell[i].onclick = this.goAction; } } // -= ! тут this - указывает на DIV, а не на объект GAME ! =- goAction(e){ var e = e.target; if(game.nextGamer == 'X'){ e.innerHTML = 'X'; game.nextGamer = 'O'; } else { e.innerHTML = 'O'; game.nextGamer = 'X'; } game.checkWins(); // после каждого хода вызываем функцию для проверки на победу } // проверяем, есть ли на игровом поле выигрышные комбинации checkWins(){ for(var i = 0; i < this.winsCombinations.length; i++){ if( this.gameCell[this.winsCombinations[i][0]].innerHTML == this.gameCell[this.winsCombinations[i][1]].innerHTML && this.gameCell[this.winsCombinations[i][1]].innerHTML == this.gameCell[this.winsCombinations[i][2]].innerHTML && this.gameCell[this.winsCombinations[i][0]].innerHTML != '' ){ this.stopGame(); // если есть, вызываем stopGame } } } // stopGame - функция завершающая игру stopGame(){ alert('Победа!'); } }; // создаем игру var game = new Game(); game.on(); </script> <style> body { background-color: #ff9800; } #wrapper{ width: 300px; height: 300px; margin: 0 auto; border: 2px solid #333; margin-top:100px; } .btn{ width: 100px; height: 100px; float: left; border: 3px solid #555; background: #f1f1f1; box-sizing: border-box; text-align: center; line-height: 100px; font-size: 55px; color: #444; font-family: sans-serif; cursor: pointer; } </style> </body> </html> |
Можно так попробовать:
this.gameCell[i].onclick = this.goAction.bind(this) |
Nexus,
спасибо - заработало! :dance: Пойду почитаю про bind :thanks: |
click лучше навесить на wrapper, юзать делегирование, и возможно, вот это https://learn.javascript.ru/behavior
в методе on проверять, что событие уже добавляли (а лучше его сделать приватным и вызывать из конструктора) |
Alexandroppolus,
спасибо за идеи - буду пробовать. |
Часовой пояс GMT +3, время: 22:11. |