为什么循环要分配最后一个索引元素的引用? [复制]

2023-11-24

我想为我的所有标签添加一个事件侦听器,每个传递一个对其自身的引用作为触发事件时的参数。这是我写的函数:

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);
    }
}

基本上该函数应该执行以下操作:

  1. 将具有指定类名的所有输入标签存储在数组中
  2. 循环遍历数组,为每个标签添加一个 id 并
  3. 添加onkeyup事件侦听器isNumberOrDot(event, tagId)处理程序。

Problem

添加了 onkeyup 事件,但每个事件的处理程序是always参考tagId数组的最后一个元素。

Question

代码/逻辑有什么问题?如何修复它?

Note

当然这个问题与循环中的 JavaScript Closure 有关,虽然这个问题可能有一个更通用的答案,但它特定于正在使用的事件侦听器。对于更高级的开发人员来说,应用通用解决方案来解决这个问题可能很容易。但对我来说,其他解决方案仍然没有提供完整的解释,甚至没有起作用。

先感谢您。


因为实际事件发生在您之后的某个时间for循环已经完成运行,因此它的索引位于最后一个值和函数中的任何局部变量,例如tagId也处于其最后的值。您需要创建某种类型的闭包来保留i or 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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么循环要分配最后一个索引元素的引用? [复制] 的相关文章

随机推荐