Javascript array.forEach(函数)执行函数的次数是预期的两倍

时间:2017-12-08 23:01:01

标签: javascript arrays foreach sleep

我有一个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()的持续时间似乎比它应该长。

1 个答案:

答案 0 :(得分:4)

除了可怕的sleep功能。您使用myFunction作为forEach的回调,而在myFunction中,您正在将新元素推送到numbers,这与您呼叫的同一个数组forEach上。

forEach在仍然循环数组的同时,不会对新推送的项目调用回调。但是在循环结束时,数组中的项目将加倍。根据MDN的说法:

  

forEach()处理的元素范围在第一次调用callback之前设置。 forEach()将不会访问在callback调用开始后附加到数组的元素。

如果数组包含N个元素,那么当点击发生时,N元素将会显示,myFunction会推送N个其他元素,并且当下一个元素时点击发生2N这次将显示元素,...

因此,每次单击后,数组中的元素将加倍。