JavaScript中的奇怪内容"for"

dmi*_*itq 8 javascript jquery closures loops for-loop

我正在使用jQuery,我有一个我不明白的奇怪的事情.我有一些代码:

for (i = 1; i <= some_number; i++) {
    $("#some_button" + i).click(function() {
        alert(i);
    });
}
Run Code Online (Sandbox Code Playgroud)

正如名字所说的"#some_button" - 它们是一些按钮.点击它们时,应该弹出一个带有它号码的方框,对吗?但他们没有.如果有4个按钮,它们总是弹出"5"(按钮计数+ 1).为什么会这样?

Hoo*_*ing 18

它与JavaScript范围有关.您可以通过添加一个函数并让该函数调用自身并传入i来引入另一个范围,从而轻松解决它:

for (var i = 1; i <= some_number; i++) {
  (function(j) {
    $("#some_button" + j).click(function() {
      alert(j);
    });
  })(i);
}
Run Code Online (Sandbox Code Playgroud)

这会创建一个闭包 - 当内部函数可以访问调用函数时不再存在的作用域时.有关更多信息,请参阅MDC上的这篇文章.

编辑:RE:自我调用函数:自调用函数是一个匿名调用的函数.您没有实例化它,也没有将它分配给变量.它采用以下形式(注意开头的parens):

(function(args) {
  // function body that might modify args
})(args_to_pass_in);
Run Code Online (Sandbox Code Playgroud)

将此与问题联系起来,匿名函数的主体将是:

$("#some_button" + j).click(function() {
  alert(j);
});
Run Code Online (Sandbox Code Playgroud)

将这些组合在一起,我们在第一个代码块中得到答案.匿名自调用函数期待一个名为的参数j.它查找id为some_button最后整数值的任何元素j(例如some_button1,some_button10).每次单击其中一个元素时,它都会警告其值j.解决方案的倒数第二行传入值i,即调用匿名自调用函数的循环计数器.换句话说,它可能看起来像这样:

var innerFunction = function(j) {
  $("#some_button" + j).click(function() {
    alert(j);
  });
};

for (var i = 1; i <= some_number; i++) {
  innerFunction(i);
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*llo 9

你在循环中遇到了一个非常常见的闭包问题for.

封闭在闭包中的变量共享相同的单个环境,因此在click调用回调时,循环将运行并且i变量将指向最后一个条目.

您可以使用函数工厂通过更多闭包解决此问题:

function makeOnClickCallback(i) {  
   return function() {  
      alert(i);
   };  
} 

var i;

for (i = 0; i < some_number; i++) {
    $("#some_button" + i).click(makeOnClickCallback(i));
}
Run Code Online (Sandbox Code Playgroud)

如果您不熟悉闭包的工作方式,这可能是一个非常棘手的主题.您可以查看以下Mozilla文章以获得简要介绍: