我的函数应该迭代文档中的所有表单,并将 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或由相同问题引起的大约一百万个其他问题。
i
和 e
每次循环时都是相同的变量:循环仅更改 i
和 e
>,它不会给你一个新的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/