我要做的是将两个独立的处理程序附加到字段的change事件中。每个处理程序都是通过循环数组并使用数组中的项来设置的,以便在运行时实现处理程序的输出 - 希望在查看示例代码时变得清晰。
代码如下:
$(document).ready( function () {
//
// Create some test input fields on the page...
//
$('<br />').insertAfter($('body > *:last'));
$('<input type="text" name="t0" id="t0" value="" />').insertAfter($('body > *:last'));
$('<input type="text" name="t1" id="t1" value="" />').insertAfter($('body > *:last'));
//
// The problematic part - for me at least...
//
var arr = new Array(1, 2);
for (var a in arr) {
// Using Chrome console here for logging
console.log("## " + a);
$('#t0').change(function () {
console.log(">> " + a)
});
}
});
因此,当我在第一个字段中添加值时,我期望发生的事情是从控制台内部(在Chrome中运行这些示例):
## 0
## 1
>> 1
>> 2
我得到的是:
## 0
## 1
>> 1
>> 1
我原本希望传递给处理程序的函数会在a
的值上形成一个闭包,我最终将两个函数绑定到处理程序,其中a
具有值1
以及a
具有值2
。
想法?
干杯 - 克里斯
答案 0 :(得分:4)
这里有两个重大错误:
首先,for (a in x)
不能像你期望的那样工作:它迭代对象属性,而不是数组元素。
另一个错误是a
在调用函数时发生了变化。实现所需功能的好方法是:
for(var a=0; a<arr.length; a++) {
(function(a) {
// now you can use "a"
})(arr[a]);
}
如果你没有创建一个闭包,看看for
循环会发生什么,请看:
var arr = [1,2,3];
var functions = [];
for(var a=0; a<arr.length; a++) {
functions.push(function() {
console.log(a);
})
}
// now execute all the functions
for(var i=0; i<functions.length; i++) {
functions[i]();
}
现在所有函数都会记录3
,这是数组中最后一个元素的索引+ 1(arr[0] == 1, arr[1] == 2, arr[2] == 3
)。会发生的是for
循环在每次迭代时创建这些函数,但是在循环结束后,a == arr.length
时会执行。
答案 1 :(得分:2)
尝试jQuery的own tool。
,而不是“for”循环 $(arr).each(function(a) {
console.log("## " + a);
$('#t0').change(function () {
console.log(">> " + a)
});
});
这可以按预期工作。
您的代码不起作用的原因是闭包使用其变量的最新值。也就是说,如果你创建一个a
等于1的闭包,然后当a
等于2时创建另一个闭包,那么两个闭包都将使用最后一个值,2。这无疑是令人困惑的,但这是这个怎么运作。
答案 2 :(得分:-1)
你必须做这样的事情:
for (var a in arr) {
(function (a) {
// thanks to closure variable a is local here
$('#t0').change(function () {
console.log(">> " + a);
});
}(a));
}
或者像这样:
for (var a in arr) {
$('#t0').change((function (a) {
return function () {
// returned function has access to local variable a from
// outer function
console.log(">> " + a);
};
}(a));
}
Trick是将变量a放在比循环更深的范围内。 为了更容易阅读上面的两个片段,可以写成:
for (var a in arr) {
(function (inner_a) {
// thanks to closure variable a is local here
$('#t0').change(function () {
console.log(">> " + inner_a);
});
}(a));
}
for (var a in arr) {
$('#t0').change((function (inner_a) {
return function () {
// returned function has access to local variable a from
// outer function
console.log(">> " + inner_a);
};
}(a));
}
顺便说一句。除非你通过对象属性进行交互,否则最好使用classic for(var i ...)而不是for .. in循环。并且$('#t0')应该被缓存:
var cachedEl = $('#t0');
for (var a=0; a < arr.length; a++) {
(function (inner_a) {
// thanks to closure variable a is local here
cachedEl.change(function () {
console.log(">> " + inner_a);
});
}(a));
}
// or
for (var a=0; a < arr.length; a++) {
cachedEl.change((function (inner_a) {
return function () {
// returned function has access to local variable a from
// outer function
console.log(">> " + inner_a);
};
}(a));
}