Javascript 在for循环中创建闭包-我这样做对吗?
我有问题。这里的代码非常密集,但我无法准确地理解下面的代码中到底发生了什么 我试图做的是将两个独立的处理程序附加到字段的更改事件。每个处理程序都是通过在一个数组上循环并使用数组中的项在运行时影响处理程序的输出来设置的-希望在查看示例代码时会变得清晰 代码如下:Javascript 在for循环中创建闭包-我这样做对吗?,javascript,jquery,Javascript,Jquery,我有问题。这里的代码非常密集,但我无法准确地理解下面的代码中到底发生了什么 我试图做的是将两个独立的处理程序附加到字段的更改事件。每个处理程序都是通过在一个数组上循环并使用数组中的项在运行时影响处理程序的输出来设置的-希望在查看示例代码时会变得清晰 代码如下: $(document).ready( function () { // // Create some test input fields on the page... //
$(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)
});
}
});
我得到的是:
## 0
## 1
>> 1
>> 1
我本以为传递给处理程序的函数会在a的值上形成闭包,最终会有两个函数绑定到处理程序,一个函数中a的值为1,另一个函数中a的值为2
想法
干杯-克里斯这里有两个大错误: 首先,x中的for a的工作方式与您期望的不同:它迭代对象属性,而不是数组元素 另一个错误是,函数在调用时会发生更改。实现所需功能的好方法如下:
for(var a=0; a<arr.length; a++) {
(function(a) {
// now you can use "a"
})(arr[a]);
}
现在所有函数都将记录3,这是数组中最后一个元素的索引+1 arr[0]==1,arr[1]==2,arr[2]==3。发生的情况是,for循环在每次迭代时创建这些函数,但当a==arr.length时,它们会在循环完成后执行。这里有两个大错误: 首先,x中的for a的工作方式与您期望的不同:它迭代对象属性,而不是数组元素 另一个错误是,函数在调用时会发生更改。实现所需功能的好方法如下:
for(var a=0; a<arr.length; a++) {
(function(a) {
// now you can use "a"
})(arr[a]);
}
现在所有函数都将记录3,这是数组中最后一个元素的索引+1 arr[0]==1,arr[1]==2,arr[2]==3。发生的情况是,for循环在每次迭代时创建这些函数,但它们在循环完成后执行,当a==arr.length。而不是for循环时,请尝试jQuery 这正是我们想要的
代码不起作用的原因是闭包使用其变量的最新值。也就是说,如果创建一个闭包时a等于1,然后在a等于2时创建另一个闭包,则两个闭包都将使用最后一个值2。这的确令人困惑,但这就是它的工作原理 不要使用for循环,而是尝试jQuery的 这正是我们想要的
代码不起作用的原因是闭包使用其变量的最新值。也就是说,如果创建一个闭包时a等于1,然后在a等于2时创建另一个闭包,则两个闭包都将使用最后一个值2。这的确令人困惑,但这就是它的工作原理 你必须这样做:
for(var a=0; a<arr.length; a++) {
(function(a) {
// now you can use "a"
})(arr[a]);
}
对于arr中的var a{
功能a{
//由于闭包变量a在这里是局部变量
$'t0'.changefunction{
console.log>>+a;
};
}a;
}
或者像这样:
诀窍是将变量a置于比for循环更深的范围内。
为了便于阅读,上述两段代码可以写成:
顺便说一句,最好是使用经典的变量i。。。而不是。。在循环中,除非通过对象属性进行交互。和$'t0'应被缓存:
var cachedEl=$'t0';
对于var a=0;a你必须这样做:
for(var a=0; a<arr.length; a++) {
(function(a) {
// now you can use "a"
})(arr[a]);
}
对于arr中的var a{
功能a{
//由于闭包变量a在这里是局部变量
$'t0'.changefunction{
console.log>>+a;
};
}a;
}
或者像这样:
诀窍是将变量a置于比for循环更深的范围内。
为了便于阅读,上述两段代码可以写成:
顺便说一句,最好是使用经典的变量i。。。而不是。。在循环中,除非通过对象属性进行交互。和$'t0'应被缓存:
var cachedEl=$'t0';
对于var a=0;a快速提示:您没有关闭文档准备功能。添加一个结束括号了解JavaScript函数作用域将有助于您:添加缺少的@musefan-thanksQuick注意:您的未结束代码
你的文件准备功能。添加一个理解JavaScript函数作用域的结束括号将对您有所帮助:添加了缺少的@musefan-thanks,感谢您的快速响应!很好地解释了我所犯的错误。现在说得通了,谢谢你。谢谢你的迅速回复!很好地解释了我所犯的错误。现在说得通了-谢谢你的回答-也有助于我的理解,谢谢!感谢您的回复-这也有助于我的理解,所以谢谢!
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));
}
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));
}