使用重复的相似行(使用循环?)简化 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个匿名函数,而避免闭环问题。
好的,我希望你看到这个时不要脸红 - 我还在摸索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个匿名函数,而避免闭环问题。