为什么循环将最后一个索引元素的引用分配给? [英] Why is the loop assigning a reference of the last index element to?

查看:21
本文介绍了为什么循环将最后一个索引元素的引用分配给?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to add an event listener to all of my tags, each passing a reference to itself as a parameter when the even is triggered. Here is the function I wrote:

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

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

Basically the function should do the following:

  1. 将具有指定类名的所有输入标签存储在一个数组中
  2. 循环遍历数组,为每个标签添加一个 id 和
  3. 使用 isNumberOrDot(event, tagId) 处理程序添加 onkeyup 事件侦听器.
  1. Store all the input tags with the specified classname in an array
  2. Loop through the array, adding an id to each tag and
  3. Adding the onkeyup event listener with the isNumberOrDot(event, tagId) handler.

问题

添加了 onkeyup 事件,但每个事件的处理程序总是引用数组最后一个元素的 tagId.

Problem

The onkeyup event is added, but they handlers of each one is always referencing the tagIdof the last element of the array.

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

What is wrong with the code/logic? And how can it be fixed?

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

Sure this problem is related to JavaScript Closure in loops, while this question could have a more general answer, it is specific to event listeners being used. To more advanced developers, it might be easy to apply the general solution to this problem. But to me the other solutions still didn't provide a full explanation or even worked.

提前致谢.

推荐答案

因为实际事件发生在 for 循环已经完成运行之后的某个时间,因此它的索引是最后一个值并且您函数中的任何局部变量(如 tagId )也处于其最后一个值.您需要创建某种闭包,为​​每个事件处理程序唯一地保留 itagId 的值,以便它们每个都可以访问自己的值.

Because the actual event occurs sometime in the future after your for loop has already finished running and thus its index is at the last value and any local variables in your function like tagId are also at their last value. You need to create some sort of closure that preserves the value of i or tagId uniquely for each event handler so they each have access to their own value.

有几种不同的方法可以做到这一点,但都涉及将 i 值传递给每个事件处理程序的函数.

There are several different ways to do that, but all involve passing the i value to a function for each event handler.

这是使用 IIFE(立即调用的函数表达式)的一个:

Here's one using an IIFE (immediately invoked function expression):

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 循环中的索引传递到闭包中,并在事件处理程序中基于它进行任何计算(尽管任一方法都可以正常工作),如下所示:

A little more common way to do this is to pass the index from the for loop into the closure and do any calculation based on it inside the event handler (though either method works fine) like this:

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

这篇关于为什么循环将最后一个索引元素的引用分配给?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆