【问题标题】:How to make my loop work with setTimeout?如何使我的循环与 setTimeout 一起工作?
【发布时间】:2019-11-26 19:54:30
【问题描述】:

changeColor 正在另一个函数中被调用。我试过这个没有循环,它工作得很好。问题是它只会显示在一个盒子上。我试图让它显示在每个盒子上,但我遇到了死胡同。我试过if和else if,它不会循环。我的代码中缺少什么?为什么它忽略循环?

function changeColor() {

    var flash = document.querySelector(".side1");

    for (var i = 0; i < flash.length; i++) {
        flash[i].style.backgroundColor = 'green'

            setTimeout(function () {
                flash[i].style.backgroundColor = 'yellow'
            }, 3000);


            setTimeout(function() {
                flash[i].style.backgroundColor = 'red'
            }, 10000);

    } 

}
setInterval(changeColor, 80000000);

【问题讨论】:

  • setInterval(changeColor, 80000000) ~ 22 小时
  • 嗯。每22小时?浏览器窗口需要打开那么久......你的用例是什么?

标签: javascript loops settimeout


【解决方案1】:

document.querySelector 只返回第一个匹配项,而不是数组。 document.querySelectorAll 将返回一个包含所有匹配项的数组。

编辑 另外,正如@Drag13 在下面指出的那样,所有超时都将使用i 的最终值,而不是您第一次设置超时时的值。要解决此问题,您可以使用let i = 0 而不是var i = 0i 置于块范围内,这意味着该块内的所有代码都将存在当前值,包括您的setTimeout 回调。

【讨论】:

  • 而且超时也会失败,因为它们总是等于 flash.length
【解决方案2】:

正如其他人所指出的,document.querySelector 仅返回元素,而不是数组。您还有变量范围问题,可以使用let 来限制范围,但它是该语言相对较新的功能。如果兼容性是一个问题,您可能希望按照 Patrick Evans 的建议找到另一种解决方案,例如闭包。这是您在功能性 sn-p 中的示例。我加快了速度并修复了 Patrick Evans 在 cmets 中指出的范围界定问题。直到。

function changeColor() {
  var flash = document.querySelectorAll("div.flash")

  for (var i = 0; i < flash.length; i++) {
    flash[i].className = 'flash green'

    // create a closure which flashes yellow
    var flashYellow = (function() {
      var f = flash[i]
      return function() {
        f.className = 'flash yellow'
      }
    })()
    // create a closure which flashes red
    var flashRed = (function() {
      var f = flash[i]
      return function(){
        f.className = 'flash red'
      }
    })()

    setTimeout(flashYellow, 1000);
    setTimeout(flashRed, 2000);
  }
}
// change color immediately
changeColor();
// change color every three seconds after that
setInterval(changeColor, 3000);
div.flash {
  height: 25vh;
  width: 25vw;
}

div.green {
  background-color: green;
}

div.yellow {
  background-color: yellow;
}

div.red {
  background-color: red;
}
<div class="flash">text</div>
<div class="flash">other text</div>

【讨论】:

  • f 将成为计时器触发时循环中的最后一个分配值。像您在答案中提到的那样使用let,或者如果在不兼容的环境中使用闭包
  • @PatrickEvans 你是对的。我已经更新了答案以包含一个说明范围问题的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 2023-01-10
  • 2019-01-05
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多