javascript - 表单迭代功能无法正常工作

标签 javascript html forms

我的函数应该迭代文档中的所有表单,并将 onclick 函数绑定(bind)到表单中的每个“计算”元素。问题是,在任何单击事件上执行的函数都是在循环中最后一个 i 的上下文中执行的。

这是我正在使用的 JavaScript:

window.onload = function(){ 
    calculateSavings();
}

function calculateSavings(){
    for (i = 0; i < document.forms.length; i++) {
        var e = document.forms[i];
        e.calculate.onclick = function() { 
            var hours = e.hours.value;
            var rate = e.rate.value;
            alert(hours * rate);
        }
    }
}

这是它所附加的 HTML:

<!doctype html>
<html>
<body>
<form>
  <label for="hours">Hours: </label><input type="text" id="hours" name="hours">
  <label for="rate">Rate: </label><input type="text" id="rate" name="rate">
  <input type="button" name="calculate" value="Calculate">
  <div id="savings"></div>
</form>
<form>
  <label for="hours">Hours: </label><input type="text" id="hours" name="hours">
  <label for="rate">Rate: </label><input type="text" id="rate" name="rate">
  <input type="button" name="calculate" value="Calculate">
  <div id="savings"></div>
</form>
</body>
</html>

我确信这是一个非常基本的问题,但目前我完全无法找到解决方案。

这是我遇到的问题的演示:http://jsfiddle.net/KcNWy/

最佳答案

您遇到了闭环问题。看,我不知道,this或由相同问题引起的大约一百万个其他问题。

ie 每次循环时都是相同的变量:循环仅更改 ie >,它不会给你一个新的e。因此,当 function() { ... } 触发时,在循环完成迭代后很长时间,e 留下了它的最终值,即最后一个匹配的输入。

(此外,您还没有声明 var i,因此 i 比这更糟糕,它是一个意外的全局变量。)

解决这个问题的典型方法是添加另一个函数作用域,以在创建时在闭包中保留值的副本:

e.elements.calculate.onclick = function(e) { 
    return function() {
        var hours = e.elements.hours.value;
        var rate = e.elements.rate.value;
        alert(hours * rate);
    }
}(e);

您可以在 ECMAScript 第五版中使用 Function#bind 方法更干净地完成此操作:

e.elements.calculate.onclick = function(e) { 
    var hours = this.elements.hours.value;
    var rate = this.elements.rate.value;
    alert(hours * rate);
}.bind(e);

但这意味着 adding support对于尚不支持此方法的现有浏览器。

或者将闭包放入循环机制本身可以避免该问题:

forEach(document.forms, function(form) {
    form.elements.calculate.onclick = function() { 
        var hours = form.elements.hours.value;
        var rate = form.elements.rate.value;
        alert(hours * rate);
    }
});

function forEach(list, callback) {
    for (var i= 0, n= list.length; i<n; i++)
        callback(list[i]);
}

或者,每次都使用相同的函数并从单击的元素中获取表单引用:

for (var i= document.forms.length; i-->0;)
    document.forms[i].elements.calculate.onclick= calculate_click;

function calculate_click() {
    var hours = this.form.elements.hours.value;
    var rate = this.form.elements.rate.value;
    alert(hours * rate);
}

关于javascript - 表单迭代功能无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4620246/

相关文章:

Javascript 使用单选按钮过滤 html 元素的可见性

javascript - 使用 jQuery 隐藏和显示数据列表的更多行

html - Bootstrap 如何排除某些元素的样式

jquery - 组合文本框和下拉列表

javascript - 为什么 html video 标签无法加载我的视频?

javascript - 带有方形单元格的可调整大小的表格

javascript - IE7 在表单中获取空值或对象值

javascript - 输入字段内的标签在聚焦时消失

php - MySQL/PHP - 表无法从我的表单获取信息

javascript - CSS 过渡没有传递随机数