Ссылка на этот элемент вне цикла for в JavaScript (JSLint)
Заранее спасибо за вашу помощь!
Я создаю простую игру в крестики-нолики, которая поможет мне изучить нативный JavaScript, поэтому моя цель - сделать как можно больше без jQuery или HTML/CSS для игры.
Я использую for-loop
создать несколько div
элементы, придерживаясь JSLint. Я прилагаю .addEventListener()
как часть процесса создания моего div
элементы для изменения цвета фона этого конкретного div
при нажатии.
Я искал Stackru, пытаясь использовать this
ссылаться на конкретный div
щелкнул. Пока я добился успеха только с помощью анонимной функции в моем for-loop
, JSLint не впечатлен, и я получаю:
Не создавайте функции внутри цикла.
Когда я пытаюсь вызвать внешнюю функцию и передать this
в целом div
процесс создания просто перестает работать, и я не уверен, почему.
Что у меня есть (это "работает"): https://jsfiddle.net/typj2LLb/4/
// create game
var gameContainer = document.getElementById('board');
var createBoard = function() {
'use strict';
var index, square;
for (index = 0; index < 9; index += 1) {
square = document.createElement('div');
square.className = 'tile';
// tile event
square.addEventListener('click', function() {
this.style.backgroundColor = 'yellow';
});
gameContainer.appendChild(square);
}
};
createBoard();
.tile {
display: inline-block;
height: 25vh;
width: 30%;
margin: 0 3px;
border: 1px solid black;
}
<body>
<div id="board"></div>
</body>
Что я думаю, что я должен делать (это не работает): https://jsfiddle.net/e4mstyy9/1/
// click-event
function changeColor(specificElement) {
'use strict';
specificElement.style.backgroundColor = 'yellow';
}
// create game
var gameContainer = document.getElementById('board');
var createBoard = function() {
'use strict';
var index, square;
for (index = 0; index < 9; index += 1) {
square = document.createElement('div');
square.className = 'tile';
// tile event
square.addEventListener('click', changeColor(this));
gameContainer.appendChild(square);
}
};
createBoard();
.tile {
display: inline-block;
height: 25vh;
width: 30%;
margin: 0 3px;
border: 1px solid black;
}
<body>
<div id="board"></div>
</body>
1 ответ
Совет не создавать функции внутри цикла уместен только в том случае, если вы ссылаетесь на переменную цикла (или что-то, производное от этой переменной) внутри функции (см. Закрытие JavaScript внутри циклов - простой практический пример того, почему).
Но так как вы этого не делаете, ваш код в порядке, и вы можете продолжать его использовать.
Почему второй пример не работает?
Когда у вас есть такое выражение, как foo(bar())
, bar
будет вызван первым, и его возвращаемое значение будет передано foo
,
В вашем коде у вас есть square.addEventListener('click', changeColor(this));
, Это означает changeColor
выполняется первым, и его возвращаемое значение передается addEventListener
,
Тем не менее, двигатель даже не заходит так далеко, потому что выполнение changeColor(this)
выдает ошибку
Uncaught TypeError: Невозможно прочитать свойство 'style' из undefined
Это потому, что ценность, которую вы передаете changeColor
(this
) не является элементом DOM. Поскольку вы используете строгий режим, значение this
является undefined
так что вы выполняете changeColor(undefined)
,
Одним из способов решения этой проблемы без создания функции внутри тела цикла было бы просто передать changeColor
вместо того, чтобы называть это (что требует от нас использовать this
снова):
// click-event
function changeColor() {
this.style.backgroundColor = 'yellow';
}
// ...
square.addEventListener('click', changeColor);
На самом деле это хорошее изменение, поскольку функция создается только один раз и используется повторно, а не для создания нового обработчика событий для каждого элемента.