Я начал создавать игру на HTML, CSS и JavaScript. Я создал функцию, которая всякий раз, когда я нажимаю кнопку, должна начать движение всех красных DIV. Однако я продолжаю получать эту ошибку в консоли:
Uncaught TypeError: Не удается прочитать свойство «стиль» неопределенного. в index.html: 48
Из-за этой ошибки DIV не перемещаются. Я использовал этот код до сих пор:
function startGame() {
var gameObj = document.getElementsByClassName("object");
for (var i = 0; i < gameObj.length; i++) {
var h = setInterval(function() {
gameObj[i].style.transition = "1s";
gameObj[i].style.left = Math.floor(Math.random() * 90) + "%";
gameObj[i].style.top = Math.floor(Math.random() * 90) + "%";
}, 500);
document.getElementById("stop").addEventListener("click", function() {
clearInterval(h);
});
}
}header {
position: absolute;
width: 100%;
height: 10%;
background-color: blue;
top: 0;
left: 0;
}
.object {
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
background-color: red;
transition: 1s;
top: 40%;
left: 30%;
}
.butn {
cursor: pointer;
color: white;
background-color: black;
border: none;
height: 50%;
width: 5%;
}<div class = "object" id = "object"></div>
<div class = "object" style = "top: 60%; left: 70%;"></div>
<header>
<button onclick = "startGame()" class = "butn">Start</button>
<button id = "stop" class = "butn">Stop</button>
</header>Когда я использовал getElementById вместо getElementsByClassName, это сработало. Однако я не могу использовать getElementById(), так как есть несколько DIV. Я использую последнюю версию Chrome. Кто-нибудь знает, как я могу это исправить? Заранее спасибо!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Переместите setInterval() на корневой уровень startGame()
function startGame() {
var h = setInterval(function() {
var gameObj = document.getElementsByClassName("object");
for (var i = 0; i < gameObj.length; i++) {
gameObj[i].style.transition = "1s";
gameObj[i].style.left = Math.floor(Math.random() * 90) + "%";
gameObj[i].style.top = Math.floor(Math.random() * 90) + "%";
}
}, 500);
document.getElementById("stop").addEventListener("click", function() {
clearInterval(h);
});
}header {
position: absolute;
width: 100%;
height: 10%;
background-color: blue;
top: 0;
left: 0;
}
.object {
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
background-color: red;
transition: 1s;
top: 40%;
left: 30%;
}
.butn {
cursor: pointer;
color: white;
background-color: black;
border: none;
height: 50%;
width: 5%;
}<div class = "object" id = "object"></div>
<div class = "object" style = "top: 60%; left: 70%;"></div>
<header>
<button onclick = "startGame()" class = "butn">Start</button>
<button id = "stop" class = "butn">Stop</button>
</header>это потому, что внутри функции setInterval переменная i не будет работать в соответствии с областью действия функции переменной.
Хорошо. Я просто новичок в JavaScript, поэтому я не знал об этом. Спасибо!
Это происходит потому, что вы используете setInterval в цикле for.
Здесь происходят две вещи -
setInterval будучи асинхронным по своей природе, принимает конечное значение i во время выполнения, которое будет 2var быть переменной с областью действия функции не сохраняет значение внутри цикла for с областью действия блокаЧтобы решить эту проблему, вы можете обернуть setInterval функцией и передать значение i в качестве аргумента. Вот так -
<html>
<head>
<style>
header {
position: absolute;
width: 100%;
height: 10%;
background-color: blue;
top: 0;
left: 0;
}
.object {
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
background-color: red;
transition: 1s;
top: 40%;
left: 30%;
}
.butn {
cursor: pointer;
color: white;
background-color: black;
border: none;
height: 50%;
width: 5%;
}
</style>
</head>
<body>
<div class = "object" id = "object"></div>
<div class = "object" style = "top: 60%; left: 70%;"></div>
<header>
<button onclick = "startGame()" class = "butn">Start</button>
<button id = "stop" class = "butn">Stop</button>
</header>
<script>
function moveElem(gameObj, i) {
var h = setInterval(function() {
gameObj[i].style.transition = "1s";
gameObj[i].style.left = Math.floor(Math.random() * 90) + "%";
gameObj[i].style.top = Math.floor(Math.random() * 90) + "%";
}, 500);
document.getElementById("stop").addEventListener("click", function() {
clearInterval(h);
});
}
function startGame() {
var gameObj = document.getElementsByClassName("object");
for (var i = 0; i < gameObj.length; i++) {
moveElem(gameObj, i);
}
}
</script>
</body>
</html>Это классическая ошибка, которую вы неизбежно совершаете при изучении Javascript. Следующие статьи помогут вам лучше понять -
Да, в этом суть. Но, похоже, i будет 2 вместо 3. Поскольку i++ позволит i стать 0, 1, 2, EOL (конец цикла), но setInterval является асинхронным, поэтому весь код станет gameObj[2], который не определен.
@CasimirCrystal Плохо, что ты прав, я думал, что видел три div, я отредактирую свой ответ
Таким образом, Closure также является решением. Просто измените код OP на for (let i = 0)..., чтобы решить проблему. Что пройдет gameObj[0] и gameObj[1] в setInterval, в этом случае проблем не будет. @Шьямак Сет
Несмотря на то, что в настоящее время браузеры поддерживают ES2015 и выше, let все еще может вызывать проблемы совместимости для старых браузеров.
Спасибо за ваш ответ! Это решило мою проблему! Однако, не могли бы вы сказать, почему это не работало раньше?