有人可以向我解释一下:
const array = [0, 1, 2, 4, 8, 16, 32, 16, 8, 4, 2, 1, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i])
}
为什么返回0 1 1 0 2 2 4 4 8 8 16 16 32,而不是一一对应的数组项?
答案 0 :(得分:3)
数字 依次出现。但是,您将无法看到它,因为您在它们之间设置了非常低的延迟。其中一些将一起出现。这些是与array[i]
具有相同值的。
为了更好地了解它们之间的延迟,我建议将array[i]
替换为array [i] * x
,其中x
是一个数字。看这个:
const array = [0, 1, 2, 4, 8, 16, 32, 16, 8, 4, 2, 1, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i] * 500)
}
0×0.5 = 0秒后将回显。
1将在1×0.5 = 0.5秒后回显。
2将在2×0.5 = 1秒后回显。
4将在4×0.5 = 2秒后回显,依此类推。
编辑:如果您要询问记录0 1 1 0
而不是0 0 1 1
的原因,则可能是因为计算机在阵列中花了一些时间,并且在到达最后的“ 0”之前,将经过1毫秒,因此现在该记录“ 1”和“ 1”了。请注意,增加日志之间的延迟可以解决此问题。
答案 1 :(得分:0)
setTimeout()-ing时,对于浏览器,0和1实际上表示相同的东西(这就是为什么零和一开始会混合的原因)。所有其他数字都正确显示了您赋予它们的延迟,因此,首先是最小的数字(它们会先安排时间),然后是2,4,等等,这些数字会稍后出现(仅稍后一点)控制台。如果按照@WaisKamal的建议放慢速度,则此定时顺序将很明显。因此,到第二个零出现时,所有其他输出都已被调度(也就是说,setTimeouts本身都按照数组的顺序发生了),然后按时间顺序运行。
答案 2 :(得分:0)
您的代码应按递增顺序记录数组元素:
0,0,1,1,2,2,3,3,4,4,16,16,32。
如果将超时更改为更大的值,它将:
const array = [0, 100, 200, 400, 800, 1600, 3200, 1600, 800, 400, 200, 100, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i])
}
您的代码无法按预期工作的原因是执行setTimeout回调的顺序。
您可以这样想-在setTimeout中定义的超时过去之后,将回调添加到某种队列中,该队列将尽快运行(记住js是单线程的)。在您的情况下,将数组最后一个元素的回调添加到第一个,第二个和第三个元素的回调之后的队列中(因为循环执行需要1毫秒以上的时间)。
答案 3 :(得分:-1)
这是因为循环的执行比setTimeout
函数延迟要快,所以这就是延迟最小的数字优先执行的原因。