循环中的JavaScript函数

spi*_*tus 3 javascript function jslint

有人可以向我解释为什么JSLint在这个例子中抱怨"循环中的函数":

  for (var i = 0; i < buttons.length; i++) {
    (function(i) {
      buttons[i].onclick = function(e) {
        t.progressBars[t.current].update(buttons[i].getAttribute("data-value"));
      }
    })(i);
  }
Run Code Online (Sandbox Code Playgroud)

但是,当我把它改为:

function makeHandler(i)
  {
    return function() {
        t.progressBars[t.current].update(buttons[i].getAttribute("data-value"));
      }
  }

  for (var i = 0; i < buttons.length; i++) {

      buttons[i].onclick = makeHandler(i);

  }
Run Code Online (Sandbox Code Playgroud)

我不太明白,因为似乎每次循环迭代都必须返回新的函数对象,即使它发生在makeHandler()函数内部.为什么第二个例子适用于JS短片?

the*_*eye 5

引用linterrors,

var elems = document.getElementsByClassName("myClass"), i;
for (i = 0; i < elems.length; i++) {
    (function (iCopy) {
        "use strict";
         elems[i].addEventListener("click", function () {
            this.innerHTML = iCopy;
         });
    }(i));
}
Run Code Online (Sandbox Code Playgroud)

我们现在拥有的东西捕获i循环的每次迭代的值.发生这种情况是因为JavaScript通过值将参数传递给函数.这意味着iCopy捕获函数内的任何方式都与i无关(除非它们恰好在该时间点具有相同的值).如果i稍后更改(它在循环的下一次迭代中执行)则iCopy不会受到影响.

这将按照我们的预期工作,但现在的问题是JavaScript解释器将在每次循环迭代中创建捕获函数的实例.它必须这样做,因为它不知道函数对象是否会在别处修改.由于函数是标准JavaScript对象,因此它们可以具有与任何其他对象相同的属性,这些属性可以在循环中更改.因此,通过在循环上下文中创建函数,可以使解释器创建多个函数实例,这可能会导致意外行为和性能问题.要解决这个问题,我们需要将该函数移出循环:

我希望Array.prototype.forEach在这里使用,就像这样

buttons.forEach(function(curButton) {
    curButton.onclick = function(e) {
        t.progressBars[t.current].update(curButton.getAttribute("data-value"));
    };
});
Run Code Online (Sandbox Code Playgroud)


Ham*_*ish 5

你的两个例子并不等同。

首先,您创建一个匿名函数并在每个循环上调用它。

内部函数(单击事件处理程序)很好 - 您正在分配一个新函数 - 但在这种情况下,匿名外部函数效率低下。在第二个示例中,外部函数被重构出循环,它只创建一次,而不是buttons.length多次。