循环遍历函数会导致错误并在第一次更改时失败

Posted

技术标签:

【中文标题】循环遍历函数会导致错误并在第一次更改时失败【英文标题】:Looping through function causes error and fails on first change 【发布时间】:2014-12-16 19:05:42 【问题描述】:

我这里有以下脚本导致我出现一些错误:

var sections = ["#general_info", "#address_records", "#employment_history", "#driver_experience", "#military_experience", "#eeo_survey", "#psp_notice", "#eva"];
for(var i = 0; i < sections.length; i++) 
    $(sections[i]).find('input, select').each(function()
        $(this).change(function()
            validate();
            $(this).closest('.placement').find('.module-heading').removeClass('module-heading-bad');
            $(this).closest('.placement').find('.glyphicon').addClass('glyphicon-ok text-success');
            $(this).closest('.placement').find('.glyphicon').removeClass('glyphicon-warning-sign text-danger');
            $(sections[i]).find('input, select').each(function()
                if($(this).closest('div').hasClass('has-error'))
                    $(this).closest('.placement').find('.module-heading').addClass('module-heading-bad');
                    $(this).closest('.placement').find('.glyphicon').addClass('glyphicon-warning-sign text-danger');
                    $(this).closest('.placement').find('.glyphicon').removeClass('glyphicon-ok text-success');
                    return false;
                
            );
        );
    );


function validate()
    var driving_qs = ['driving_exp_qa', 'driving_exp_qb', 'driving_exp_qc', 'driving_exp_qd'];
    for( var i = 0; i < driving_qs.length; i++)
        if($('input[name='+driving_qs[i]+']:checked').val())
            $('input[name='+driving_qs[i]+']').closest('.form-group').removeClass('has-error');
            $('input[name='+driving_qs[i]+']').closest('.form-group').addClass('has-success');
        else
            $('input[name='+driving_qs[i]+']').closest('.form-group').addClass('has-error');
            $('input[name='+driving_qs[i]+']').closest('.form-group').removeClass('has-success');
        
    
    var fields = [
        selector: $('.not-empty'),
        validations: [ isNotEmpty]
    ,
        selector: $('.email'),
        validations: [ isNotEmpty, isEmail]
    ,
        selector: $('.number'),
        validations: [ isNotEmpty, isNumber]
    ,
        selector: $('.number-noreq'),
        validations: [isNumberNotRequired]
    ];
    $('.form-control').closest('div').removeClass('has-error');
    var i = 0, k = 0, z = 0, j = fields.length, item, selector, fn, info;
    for(; i < j; i++)
        item = fields[i];
        for(k = 0; k < item.validations.length; k++)
            fn = item.validations[k];
            for( z = 0; z < item.selector.length; z++)
                selector = $(item.selector[z]);
                info = selector.closest('div');
                if(info)
                    var result = fn(selector.val());
                if(result)
                    info.removeClass("has-error");
                    info.addClass('has-success');
                else
                    info.removeClass('has-success');
                    info.addClass("has-error")
                
            
        
    

如果我在没有前面的 for 循环的情况下运行脚本,则该脚本可以正常工作。下面是我的代码的快速一步一步(注意:这是没有 for 循环):

    在代码中找到该部分并找到每个输入一个选择字段 将更改事件分配给每个目标输入和选择字段 在更改时找到最近的类放置范围,并细化第一个模块标题并执行所有类的添加和删除,如果下面没有错误,则将标题刷新为成功标题。 查找所有输入和选择并检查错误,如果存在则返回 false,然后将错误类重新添加到所有内容中

这个脚本将一直运行到每个部分的末尾,就像它应该做的那样。然而,在我尝试使用for loop 执行此操作后,它仅在一次输入后创建了一个成功场景。为什么会发生这种情况,甚至可以像我目前正在做的那样在循环中使用这个函数吗?

下面我还包含了 html 标记的示例

<!-- this tag serves no purpose other than being a bookmark for scripting -->
<span class='placement'>
    <!-- Section 1: General Information  -->
    <div id='general-heading' class='row module-heading module-heading-bad general' data-toggle='#general_info'>
        <div class='form-group'>
            <div class='col-md-12'>
                <h4 class='text-info '>General Information<div id='general-confirmation' class='glyphicon glyphicon-warning-sign pull-right text-danger'></div></h4>    
            </div>
        </div>
    </div>
    <div id='general_info' class='app-section'>
        <div class='form-group'>
            <div class='col-xs-12'>
                <div class='form-group row'>
                    <div class='col-sm-6 col-xs-12'>    
                        <label class='control-label'>First Name<span class='req'> *</span></label><br />
                        <input type='text' class='form-control not-empty' id='first_name' value="<?=$first_name?>"/>
                    </div>
                    <div class='col-sm-6 col-xs-12'>
                        <label class='control-label'>Middle Name</label><br />
                        <input type='text' class='form-control' id='middle_name' value="<?=$middle_name?>"/>
                    </div>
                </div>
            </div>
        </div>
</span>

【问题讨论】:

您的代码末尾缺少 &lt;/div&gt;if(info) 缺少一对 div 部分只是一个示例,我提取的不是实际的代码块,所以 div 在那里,但用于校对! 始终尝试发布 Short, Self Contained, Correct Example (SSCCE) 来证明您的问题。这意味着您发布的代码应该能够说明您遇到的问题。 我看到与您的参考文献略有相似之处,但这还不足以确定我在这里所做的事情的答案。 要排除人们在 for 循环中移动代码时遇到的明显问题,请尝试将 for 循环中的所有内容包装在一个闭包中:for(...) function(e,i)...original code...(e,i) 【参考方案1】:

这段代码的问题:

for(var i = 0; i < sections.length; i++) 
    $(sections[i]).find('input, select').each(function()
        $(this).change(function()
            ...
            $(sections[i]).find('input, select').each(function()
                ...
                
            );
        );
    );

是不是它使用了变量i,当change里面的function()运行时这个变量会改变。

在您的情况下,修复它的最简单方法是使用 forEach 函数而不是 for 循环,并且根本不使用索引:

sections.forEach(function(section) 
    $(section).find('input, select').each(function()
        $(this).change(function()
            ...
            $(section).find('input, select').each(function()
                ...
                
            );
        );
    );
)

这将确保您所说的i 每次都不同。

【讨论】:

你太棒了!现在我想到了你所说的关于 i 变化的说法,这是有道理的 @MarkHill 不客气。此外,如果您使用 forEach 方法,您可以将 sections[i] 替换为 forEach 回调的第一个参数,即 e。但首先重命名e 变量以使其更具可读性。 啊,谢谢你,这是一次非常有帮助的学习经历

以上是关于循环遍历函数会导致错误并在第一次更改时失败的主要内容,如果未能解决你的问题,请参考以下文章

PHP MySQL循环遍历行并在日期更改时打印日期

Linux使用while循环同ssh命令导致只能遍历一次的问题

期待错误处理 - spawn id未打开

PHP中数组遍历的几种方法

第一次作业

微信小程序中的循环遍历问题