for (id = 50; id < 100; id++)
{
if($('#'+id).attr('class') == 'myField')
{
$('#'+id).bind('click', function() { install(id); } );
}
}
不知道为什么id无法在function()中达到'install'。我试图用click事件绑定每个按钮(id为50到100)以触发install(id)函数。但似乎变量id无法达到安装功能。虽然我硬编码:
for (id = 50; id < 100; id++)
{
if($('#'+id).attr('class') == 'myField')
{
$('#'+id).bind('click', function() { install( 56 ); });
}
}
它有效!请告诉我原因。
答案 0 :(得分:4)
你所做的是使用Javascript闭包时最常见的错误之一。
顺便说一句,这个错误如此常见的事实是IMO证明它确实是语言本身的“错误”。
Javascript支持读写闭包,因此当您在闭包中捕获变量时,它不是捕获的变量的当前值,而是变量本身。 这意味着例如在
中var arr = [];
for (var i=0; i<10; i++)
arr.push(function(){alert(i);});
数组中的10个函数中的每一个都将包含一个闭包,但它们都将引用循环中使用的相同i
变量,而不是该变量在闭包时所具有的值。创建。因此,如果您调用它们中的任何一个,则输出将是相同的(例如,如果您在循环之后立即调用它们,则为10
。)
幸运的是,解决方法很简单:
var arr = [];
for (var i=0; i<10; i++)
arr.push((function(i) {
return (function(){alert(i);});
})(i));
使用这个“包装”你正在调用一个匿名函数,在该函数中,变量i
与循环不同,实际上是每个调用的不同变量。在函数i
内部只是一个参数,返回的闭包绑定到该参数。
在您的情况下,解决方案是:
for (id = 50; id < 100; id++)
{
if($('#'+id).attr('class') == 'myField')
{
$('#'+id).bind('click',
(function(id){
return (function() { install(id); });
})(id));
}
}
答案 1 :(得分:3)
未达到install()
,我想你的意思是说你的所有install(id)
行为都像install(100)
。
这是由javaSctipt闭包引起的。此行function() { install(id) }
将id
分配给install()
回调函数。在id
被调用之后,install()
的值将在循环结束后很晚才会被解析 - id
已经达到100的时间。
id
值。for (id = 50; id < 100; id++)
{
if($('#'+id).attr('class') == 'myField')
{
(function (id) {
$('#'+id).bind('click', function() { install(id); });
}) (id);
}
}
var funcCollections = [];
for (id = 50; id < 100; id++)
{
if(true)
{
(function () {
var thatId = id;
funcCollections.push(function () {console.log(thatId,id)});
}) ();
}
}
// funcCollections[1]();
// 51 100
// undefined
// funcCollections[2]();
// 52 100
答案 2 :(得分:1)
您无法将变量传递给您绑定的函数。它失去了val。当你传递'56'时它总是56,但是当你传递一个var时,JavaScript不会绑定循环中var的值。
答案 3 :(得分:1)
当你遍历变量并创建引用循环变量的匿名函数(闭包)时,它们将引用最后一个值
另请注意,您不必将循环变量的范围限制为for循环(它未使用var声明),这意味着稍后对该变量的修改将传播到所有闭包。
看看this
答案 4 :(得分:1)
归结为variable scope。
您绑定到$('#' + id)
元素的click事件的匿名函数无法识别示例代码中的id
变量(假设您的示例代码是函数的摘录) )。即使它确实如此(例如你在任何函数之外声明id
,给它全局范围),id
将在调用click事件时保持值 100 ,这不是不是你想要的。
但是,您可以使用$(this).attr('id')
来获取元素的id
值:
for (id = 50; id < 100; id++)
{
if($('#' + id).attr('class') == 'myField')
{
$('#' + id).bind('click', function()
{
install(parseInt($(this).attr('id')));
});
}
}
查看jQuery .bind()
文档,其中显示了如何在事件处理程序中使用this
。