Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 28.11.2017, 19:41
Аватар для void()
Профессор
Отправить личное сообщение для void() Посмотреть профиль Найти все сообщения от void()
 
Регистрация: 11.08.2017
Сообщений: 208

Проблема с контекстом и 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>
Ответить с цитированием
  #2 (permalink)  
Старый 28.11.2017, 19:52
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,795

Можно так попробовать:
this.gameCell[i].onclick = this.goAction.bind(this)
Ответить с цитированием
  #3 (permalink)  
Старый 28.11.2017, 19:56
Аватар для void()
Профессор
Отправить личное сообщение для void() Посмотреть профиль Найти все сообщения от void()
 
Регистрация: 11.08.2017
Сообщений: 208

Nexus,
спасибо - заработало! Пойду почитаю про bind
Ответить с цитированием
  #4 (permalink)  
Старый 28.11.2017, 20:03
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

click лучше навесить на wrapper, юзать делегирование, и возможно, вот это https://learn.javascript.ru/behavior


в методе on проверять, что событие уже добавляли (а лучше его сделать приватным и вызывать из конструктора)
Ответить с цитированием
  #5 (permalink)  
Старый 29.11.2017, 06:34
Аватар для void()
Профессор
Отправить личное сообщение для void() Посмотреть профиль Найти все сообщения от void()
 
Регистрация: 11.08.2017
Сообщений: 208

Alexandroppolus,
спасибо за идеи - буду пробовать.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с радио кнопками px379 Общие вопросы Javascript 8 29.07.2013 09:30
Проблема с обработкой ескольких .hover() anocean jQuery 3 15.06.2012 22:43
Проблема с Popup окном vovuslik jQuery 5 12.06.2010 16:12
Проблема с дизайном после отправки xmlhttprequest, Проблема с дизайном после отправки cyberx AJAX и COMET 3 01.05.2010 17:07
Проблема спама lliberty AJAX и COMET 1 12.03.2009 16:47