使用重复的相似行(使用循环?)简化 javascript 函数

Simplifying a javascript function with repeated similar lines (with a loop?)

好的,我希望你看到这个时不要脸红 - 我还在摸索javascript。

我正在为一个婚礼网站整理一份 RSVP 表格。

我希望客人能够将他们的名字添加到 RSVP 表单中,但只显示所需的字段。为此,在每个姓名字段之后,有一个 link 可以单击,单击后将显示下一位客人的姓名字段。

下面的代码有效...但我相信它可以更整洁。

我尝试以几种不同的方式在代码中插入 for() 循环,我可以看到 for() 循环正确递增到最后一个值 - 但是当它这样做时,它只留下最后一个添加事件监听器到位。我只能假设,我应该使用不同类型的循环 - 或者完全不同的方法。

我应该如何整理以下内容?

<script>
function showNextGuest(i) {
document.getElementsByTagName(\'fieldset\')[i].style.display = \'block\';
}

function initiateShowNextGuest() {
        document.getElementsByTagName('fieldset')[0].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(1);},false);
        document.getElementsByTagName('fieldset')[1].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(2);},false);
        document.getElementsByTagName('fieldset')[2].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(3);},false);
        document.getElementsByTagName('fieldset')[3].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(4);},false);
        document.getElementsByTagName('fieldset')[4].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(5);},false);
}

window.onload = initiateShowNextGuest();
</script>
function nextGuest () {
    for(var i = 0; i < 5; i++){
        document.getElementsByTagName('fieldset')[i]
                .getElementsByTagName('a')[0]
                .addEventListener('click',function(){ 
                       showNextGuest(parseInt(i + 1));
                 }, false);
    }
}

您的直觉是正确的 - for 循环确实可以简化它,查询选择器也可以:

var fieldsSet = document.querySelectorAll("fieldset"); // get all the field sets
var fieldss = [].slice.call(asSet); // convert the html selection to a JS array.
fields.map(function(field){
    return field.querySelector("a");  // get the first link for the field
}).forEach(function(link, i){
    // bind the event with the right index.
    link.addEventListener("click", showNextGuest.bind(null, i+1), false); 
});

这可以缩短为:

var links = document.querySelectorAll("fieldset a:first-of-type");
[].forEach.call(links, function(link, i){
     link.addEventListener("click", showNextGuest.bind(null, i+1), false); 
});

上面Benjamin的回答是最好的,所以我接受了。

不过,为了完整起见,我想展示一下我最后使用的(更简单,但不太优雅)解决方案,以便未来的读者可以将问题中的代码与下面的代码进行比较和对比:

<script>
var initiateShowNextGuest = [];

function showNextGuest(j) {
    document.getElementsByTagName('fieldset')[j].style.display = 'block';
}

function initiateShowNextGuestFunction(i) {
    return function() {
        var j = i + 1;
        document.getElementsByTagName('fieldset')[i].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(j);},false);
    };
}

function initiateShowNextGuests() {
    for (var i = 0; i < 5; i++) {
        initiateShowNextGuest[i] = initiateShowNextGuestFunction(i);
        initiateShowNextGuest[i]();
    }
}

window.onload = initiateShowNextGuests();
</script>

综上所述,函数initiateShowNextGuests()循环(然后执行)initiateShowNextGuestFunction(i)5次,设置原题代码中手动写出的5个匿名函数,而避免闭环问题。