Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 对于未按预期工作的循环,我做错了什么?_Javascript_Loops - Fatal编程技术网

Javascript 对于未按预期工作的循环,我做错了什么?

Javascript 对于未按预期工作的循环,我做错了什么?,javascript,loops,Javascript,Loops,我正在制作一个表单,用户可以为自己和最多5个其他人进行RSVP。每位客人的姓名都有一个文本字段,然后是单选按钮(是或否),显示他们是否出席。默认情况下,将显示Guest 1和Guest 2,然后用户可以单击一个按钮添加另一个Guest,直到Guest#6 客人的3-6个物品包含在他们自己的物品中,如下所示: var guestThree = { name : document.querySelector('label[for="nameOfThirdGuest"]'), attendin

我正在制作一个表单,用户可以为自己和最多5个其他人进行RSVP。每位客人的姓名都有一个文本字段,然后是单选按钮(是或否),显示他们是否出席。默认情况下,将显示Guest 1和Guest 2,然后用户可以单击一个按钮添加另一个Guest,直到Guest#6

客人的3-6个物品包含在他们自己的物品中,如下所示:

var guestThree = {
  name : document.querySelector('label[for="nameOfThirdGuest"]'),
  attendingYes : document.querySelector('label[for="guestThreeAttendingYes"]'),
  attendingNo : document.querySelector('label[for="guestThreeAttendingNo"]')
};
var guestFour = {
  name : document.querySelector('label[for="nameOfFourthGuest"]'),
  attendingYes : document.querySelector('label[for="guestFourAttendingYes"]'),
  attendingNo : document.querySelector('label[for="guestFourAttendingNo"]')
};
var guestFive = {
  name : document.querySelector('label[for="nameOfFifthGuest"]'),
  attendingYes : document.querySelector('label[for="guestFiveAttendingYes"]'),
  attendingNo : document.querySelector('label[for="guestFiveAttendingNo"]')
};
var guestSix = {
  name : document.querySelector('label[for="nameOfSixthGuest"]'),
  attendingYes : document.querySelector('label[for="guestSixAttendingYes"]'),
  attendingNo : document.querySelector('label[for="guestSixAttendingNo"]')
};
我使用以下函数隐藏guest的3-6,然后将其转换为上述对象的方法:

function hideFields() {
  this.name.style.display = "none";
  this.attendingYes.style.display = "none";
  this.attendingNo.style.display = "none";
}
在showFields中,我还有与上述功能相反的功能:

function showFields() {
  this.name.style.display = "block";
  this.attendingYes.style.display = "block";
  this.attendingNo.style.display = "block";
}
因此,这里的想法是,当单击addGuest按钮(分配给变量addGuest)时,将添加guest#3。然后再次单击时,将添加来宾4,依此类推,直到6。我已将guestThree-guestSix对象添加到以下数组中:

var extraGuests = [guestThree, guestFour, guestFive, guestSix];
然后使用以下for循环:

for (var guest = 0; guest < extraGuests.length; guest++) {
  addGuest.onclick = function() {
      extraGuests[guest].showFields();
  };
}
for(var guest=0;guest
但这不起作用。通过测试,我发现guest循环一直循环到4,而没有执行showFields方法。如果我要在onclick事件之后添加一个break,那么guestThree将显示,但仅此而已(显然,因为break就是这样工作的),但这至少表明循环在某种程度上如我所希望的那样工作

所以我要问的是,我做错了什么?如何使来宾变量不直接循环到4?我需要每个迭代都是0,1,2,最后是3,就我所能看到的,这就是应该发生的事情

干杯

您已经,这意味着在调用它们时,您的单击处理程序都在查看单个值
guest
,该值将是
extraguest.length
(循环完成时确定的值)

您需要在循环执行时捕获循环变量:

for(var guest=0;guest

使用较新的语言功能可能有更好/更简洁的方法来实现这一点。

有两个问题:

第一个是在每个循环上覆盖
addGuest
上的
onclick
,因此只有最后一个赋值仍然存在。因此,如果我们解决了第二个问题(如下),您仍将只显示最后一组字段。也许,我们希望处理程序分配一次,并让它显示“下一个”字段集

第二个问题是,您分配给
onclick
的函数具有对
guest
变量的持久引用,而不是创建函数时该变量的副本。因此,稍后调用该函数时,它会看到
guest
for
循环结束后的值。解决该问题的主要选择是构建器函数和
函数#bind
,如下所述。但既然我们不需要或不想要循环,那就没关系了

相反,我建议使用一个变量来告诉您下一组要显示的字段是什么,然后使用一个函数:

var extraGuests = [guestThree, guestFour, guestFive, guestSix];
var nextGuest = 0;
addGuest.onclick = function() {
    var guest = extraGuests[nextGuest];
    if (guest) {
        ++nextGuest;
        guest.showFields();
    }
};
也许是这个

var guest = 0;
addGuest.addEventListener('click', function() {
  if(guest < extraGuests.length)
    extraGuests[++guest].showFields();
}, false);
var-guest=0;
addGuest.addEventListener('click',function(){
if(客人<额外客人长度)
外部来宾[++guest].showFields();
},假);

您已在循环变量上闭合。请参阅:为什么要编写单独的函数来显示元素?有一些更简单的方法可以在方法中使用更少的复制/粘贴来实现它。我认为发生的事情是,它循环0-3次,但每次它都会重新写入上一个函数。最后你只能得到最终的结果,因为所有其他的结果都被覆盖了。如果数组的长度是5,那么函数将只显示元素5等。谢谢你,但是你发布的代码只显示guestSix,没有显示之前的元素?谢谢你,但是与其他人的解决方案一样,这两种方法都只显示guestSix,没有显示之前的元素?@SpaceGoat:我刚刚意识到:你在每次传递时覆盖
addGuest
对象上的单击处理程序。它的正确实现需要找到第一个未显示的字段集并显示它。请注意,使用一组名为“nameOfSixthGuest”的字段通常表示您希望以不同的方式进行操作。在这种情况下,您可能只想在需要时动态添加字段,而不是预先创建您可能不使用的字段,然后显示它们。@SpaceGoat:现在我更好地理解了这个问题,我已经更新了解决方案。啊,是的,这确实有意义。我可以使用Javascript将来宾3-6写入DOM,而不是在HTML中创建它们。这样我就不必费劲地把它们藏起来,也不必费那么大的劲了!我将尝试重新编写我的代码…刚刚尝试了你的新解决方案,它工作得非常完美。谢谢你,伙计!
var guest = 0;
addGuest.addEventListener('click', function() {
  if(guest < extraGuests.length)
    extraGuests[++guest].showFields();
}, false);