У меня есть html файл с одной кнопкой на нем
<!DOCTYPE html>
<html> <body>
<p>Click the button to list all the items in the array.</p>
<button onclick = "numbers.forEach(myFunction)" >Try it</button>
<p id="demo"></p>
</body>
</html>
У меня также есть файл Javascript, содержащий функцию onclick
для метода .forEach
.
Когда нажимается кнопка, я бы хотел пройти через массив, перейдя через каждый экземпляр элемента в массиве.
Для каждого элемента в этом массиве я хотел бы распечатать его индекс и значение с последующим таймером, который ждет вторую, чтобы отобразить следующую перестановку.
demoP = document.getElementById("demo");
var numbers = [];
var random = Math.floor(Math.random() * 4) + 1;
numbers.push(random);
function myFunction(item, index) {
random = Math.floor(Math.random() * 4) + 1;
numbers.push(random);
demoP.innerHTML = demoP.innerHTML + "numbers[" + index + "]: " + item + "<br>";
//demoP.innerHTML = demoP.innerHTML + "<br>" //add magic spacing between permutation
sleep(100);
//switch to this and see how slow?
//sleep(1000);
}
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
Что бы я хотел, чтобы результат показывал, когда пользователь нажимает кнопку:
numbers[0] = 4
//waits a second and adds a <br> here to separate
numbers[0] = 4
numbers[1] = 2
//waits a second and adds a <br> here
numbers[0] = 4
numbers[1] = 2
numbers[2] = 3
и так далее.
В настоящее время код выводит как минимум в два раза больше элементов, а sleep(), по-видимому, длится дольше, чем нужно.
Помимо отвратительной функции sleep
. Вы используете myFunction
как обратный вызов forEach
, а в myFunction
вы нажимаете новые элементы на numbers
которые являются тем же самым массивом, который вы вызываете для forEach
.
forEach
не будет вызывать обратный вызов для вновь выдвинутых элементов, все еще продолжая цикл массива. Но к концу цикла элементы в массиве будут удвоены. Как указано в MDN:
Диапазон элементов, обработанных
forEach()
, устанавливается перед первым вызовомcallback
. Элементы, которые добавляются в массив после вызоваforEach()
, не будут посещатьсяcallback
.
Если массив содержит N
элементов, то при щелчке будет показано N
элементов, а myFunction
будет нажимать N
других элементов, а когда следующий щелчок произойдет, на этот раз будут показаны 2N
элементы,...
Поэтому после каждого щелчка элементы в массиве будут удвоены.
sleep
. Вместо этого узнайте, как выполнять асинхронные вызовы через что-то вродеsetTimeout
илиsetInterval
. Также рассмотрите возможность использованияconsole.log
для отслеживания вашего кода во время его работы. А так как вы меняетеnumbers
массивов при выполненииforEach
вы просите о проблемах. И делатьforEach
в атрибутеonclick
элемента DOM - не лучший способ. Сделайте так, чтобыonclick
вызывал функцию и выполнялforEach
в этой функции.