我想为所有标记添加一个事件监听器,每个标记都会在触发偶数时将其作为参数传递给自身。这是我写的函数:
function validateDigitsFeature()
{
// Add the event listeners to input tags
// Get the array of input tags
var inputTags = document.getElementsByClassName('validateInput');
var tagId;
// Loop through them, adding the onkeypress event listener to each one
for (var i = 0; i < inputTags.length; i++)
{
// Give each input element an id
tagId = inputTags[i].id = 'input_id_' + i;
inputTags[i].addEventListener('keyup', function(){isNumberOrDot(event, tagId);}, false);
}
}
基本上该功能应该执行以下操作:
onkeyup
处理程序添加isNumberOrDot(event, tagId)
事件侦听器。添加了onkeyup事件,但每个人的处理程序始终引用数组最后一个元素的tagId
。
代码/逻辑有什么问题?它怎么能修复?
当然这个问题与循环中的JavaScript Closure有关,而这个问题可能有更一般的答案,它特定于正在使用的事件监听器。对于更高级的开发人员,可能很容易将常规解决方案应用于此问题。但对我来说,其他解决方案仍未提供完整的解释,甚至无法解决。
提前谢谢。
答案 0 :(得分:6)
因为实际事件在您的for
循环已经完成运行后的某个时间发生,因此其索引位于最后一个值,并且函数中的任何局部变量(如tagId
)也在最后的价值。您需要创建某种闭包,为每个事件处理程序唯一保留i
或tagId
的值,以便它们各自可以访问自己的值。
有几种不同的方法可以做到这一点,但都涉及将i
值传递给每个事件处理程序的函数。
这是一个使用IIFE(立即调用的函数表达式):
function validateDigitsFeature()
{
// Add the event listeners to input tags
// Get the array of input tags
var inputTags = document.getElementsByClassName('validateInput');
// Loop through them, adding the onkeypress event listener to each one
for (var i = 0; i < inputTags.length; i++)
{
// Give each input element an id
(function() {
// creates a unique function context for each event handler so the
// value of tagId is unique for each event handler
var tagId = inputTags[i].id = 'input_id_' + i;
inputTags[i].addEventListener('keyup', function(){isNumberOrDot(event, tagId);}, false);
})();
}
}
执行此操作的一种更常见的方法是将索引从for
循环传递到闭包中,并在事件处理程序内基于它进行任何计算(尽管任一方法都可以正常工作),如下所示:
function validateDigitsFeature()
{
// Add the event listeners to input tags
// Get the array of input tags
var inputTags = document.getElementsByClassName('validateInput');
// Loop through them, adding the onkeypress event listener to each one
for (var i = 0; i < inputTags.length; i++)
{
// Give each input element an id
(function(index) {
// passes the `for` loop index into a function closure
// so it is uniquely preserved for each event handler
inputTags[index].addEventListener('keyup', function(){
isNumberOrDot(event, inputTags[index].id = 'input_id_' + index);
}, false);
})(i);
}
}