对于循环,setTimeout无法按预期工作

时间:2017-05-06 13:42:04

标签: javascript for-loop

以下代码按预期工作。

var mySelector = document.querySelectorAll('.mySelector');
var myFunction = function() {
  for (var i = 0; i < mySelector.length; i++) {
    mySelector[i].classList.add('myClass');
  }
}

但是,此代码会生成错误:&#34;未捕获的TypeError:无法读取属性&#39; classList&#39;未定义&#34;

var mySelector = document.querySelectorAll('.mySelector');
var myFunction = function() {
  for (var i = 0; i < mySelector.length; i++) {
    setTimeout(function(i){
      mySelector[i].classList.add('myClass');
    }, 1000);
  }
}

我确定有一个非常简单的解释,为什么会这样,但我不知道。

为什么?

更新:从setTimeout函数中删除参数的新代码

var mySelector = document.querySelectorAll('.mySelector');
var myFunction = function() {
  for (var i = 0; i < mySelector.length; i++) {
    setTimeout(function(){
      mySelector[i].classList.add('myClass');
    }, 1000);
  }
}

更新2:

Barmar建议这与另一个问题完全相同:JavaScript closure inside loops – simple practical example

我承认它通常是相似的,并且Barmar链接到的答案可能可以帮助那些拥有更多JavaScript体验的人,而不是我所面临的驼峰。但我认为我的问题不同,只能保持开放,原因如下:(1)我的案例更简单,正确的答案可能会使像我这样的技能较低的JavaScript从业者受益,(2)我&#39; m特别关注setTimeout,因为它与for循环有关。再说一遍,我会批准Barmar引用的答案对许多人有帮助,但对我个人来说并不是特别有帮助。

2 个答案:

答案 0 :(得分:0)

js循环有一个简单的情况。因为js执行代码异步,变量$(document).ready(function() { previousScroll=0 //this means we are starting from top $(window).scroll(function() { var currentScroll = window.pageYOffset || document.documentElement.scrollTop; if (currentScroll > previousScroll){ // Change header style cause you are down scrolling } else { // Do something else? You are up scrolling anyway... } previousScroll = currentScroll; ); }); i的有效索引更多。您可以使用mySelector代替let i,或使用js闭包。 Here您可以找到有关此内容的更多信息。

答案 1 :(得分:0)

正如Carcigenicate所说,你无法访问我。以下将只打印undefined。

var mySelector = document.querySelectorAll('.mySelector');
var myFunction = function() {
  for (var i = 0; i < mySelector.length; i++) {
    setTimeout(function(i){
      console.log(i);
    }, 1000);
  }
}

myFunction();
<div class='mySelector'></div>
<div class='mySelector'></div>
<div class='mySelector'></div>
<div class='mySelector'></div>
<div class='mySelector'></div>

试试这个:

var mySelector = document.querySelectorAll('.mySelector');
var myFunction = function() {
  for (var i = 0; i < mySelector.length; i++) {
    setTimeout(addClass(i), 1000);
  }
}

myFunction();

function addClass(i) {
  return function() {
    mySelector[i].classList.add('myClass');
  }
}
<div class='mySelector'>1</div>
<div class='mySelector'>2</div>
<div class='mySelector'>3</div>
<div class='mySelector'>4</div>
<div class='mySelector'>5</div>