JavaScript 中 setInterval 与 setTimeout 的混淆

Confusion of setInterval with setTimeout in JavaScript

我正在尝试在 JavaScript 中使用 setInterval 和 setTimeout。

var temArr = []

let timer = setInterval(() => {
  var target = Math.random()
  temArr.push(target)
  console.log(6, target, temArr[temArr.length - 1], target === temArr[temArr.length - 1]) // one

  setTimeout(() => {
    console.log(9, target, temArr[temArr.length - 1], target === temArr[temArr.length - 1]) // two
  }, 500);
}, 100)

setTimeout(() => {
  clearInterval(timer)
}, 10000);

我预计一和二的最后一个值是真的。

我预计每次记录器打印时,一和二的第三个参数值相同,即target equals temArr[temArr.length - 1]

但结果是一个为真,两个为假

但是二的中间结果为假,最后一个值为真,而一始终为真

当我切换超时值时,结果为真,这意味着设置间隔值 500 和超时值 100,此时,每次记录器打印时,target === temArr[temArr.length - 1] 始终为真

你能告诉我为什么吗?

它们都为我返回了 true,只是顺序不同:

还行 setInterval VS setTimeout:

setInterval - 将 运行 每 x 毫秒内的函数。这意味着:

setInterval(() => {
  console.log('I will run every 100ms')
}, 100)

将 运行 每 100 毫秒。

setTimeout - 将 运行 函数在 x 毫秒之后。这意味着:

setTimeout(() => {
   console.log('I will run after 10 seconds')
}, 10000);

将在 10 秒后 运行。


这样做:

let timer = setInterval(() => {
  console.log('I will run every 500ms';   

  setTimeout(() => {
    cosole.log('I will run AFTER 500ms EVERY 500ms');
  }, 500);
}, 100)

setTimeout 中的日志将在第一个日志被触发后 运行 500 毫秒,并且每 100 毫秒触发一次。


编辑 - 对用户编辑问题的回答:

为了更清晰的日志,我修改了你的代码:

var temArr = []
var intervalOrder = 0;
var timeoutOrder = 0;

var timer = setInterval(() => {
  var target = Math.random()
  temArr.push(target)
   intervalOrder++

  console.log('ONE - SET TIMEOUT: ', {order: intervalOrder, target, tem: temArr[temArr.length - 1], result: target === temArr[temArr.length - 1]})

  setTimeout(() => {
timeoutOrder++
    console.log('TWO - SET TIMEOUT: ', {order: timeoutOrder, target, tem: temArr[temArr.length - 1], result: target === temArr[temArr.length - 1]}) // two
  }, 500);
}, 100)

setTimeout(() => {
  clearInterval(timer)
}, 1000);

注意到 TWO - SET TIMEOUTONE - SET TIMEOUT 获取的结果不同吗?这是因为它在调用时不获取该变量的值,但它获取 ON TRIGGER 这意味着该值已经更改,因为 setInterval 的时间更短。

为此你可以做的是在不同的函数上调用 setTiemout,这样它将在参数而不是新生成的参数上引用它的值。

var temArr = []
var intervalOrder = 0;
var timeoutOrder = 0;

var logSecond = (target) => {

  setTimeout(() => {
timeoutOrder++
    console.log('TWO - SET TIMEOUT: ', {order: timeoutOrder, target, tem: temArr[temArr.length - 1], result: target === temArr[temArr.length - 1]}) // two
  }, 500);
}

var timer = setInterval(() => {
  var target = Math.random()
  temArr.push(target)
   intervalOrder++

  console.log('ONE - SET TIMEOUT: ', {order: intervalOrder, target, tem: temArr[temArr.length - 1], result: target === temArr[temArr.length - 1]})
logSecond(target)
}, 100)

setTimeout(() => {
  clearInterval(timer)
}, 1000);

^^ 在上面的代码片段中,两个日志的目标和结果现在相同。