代码之家  ›  专栏  ›  技术社区  ›  Ernelli

如何修复jslint错误“不要在循环中生成函数”?

  •  59
  • Ernelli  · 技术社区  · 14 年前

    我正在努力使我们所有的JS代码都能通过jslint,有时会对获取遗留代码的选项进行很多调整,以便以后能够正确地修复它。

    有一件事jslint抱怨我没有一个解决方法。也就是说,当使用这样的构造时,我们会得到错误“Don't make functions within a loop”

    for (prop in newObject) {
        // Check if we're overwriting an existing function
        if (typeof newObject[prop] === "function" && typeof _super[prop] === "function" &&
            fnTest.test(newObject[prop])) {
            prototype[prop] = (function(name, func) {
                return function() {
                    var result, old_super;
    
                    old_super = this._super;
                    this._super = _super[name];
                    result = func.apply(this, arguments);
                    this._super = old_super;
    
                    return result;
                };
            })(prop, newObject[prop]);
        }
    }
    

    此循环是经典继承的JS实现的一部分,其中扩展现有类的类在调用扩展类的成员时保留扩展类的超级属性。 只是想澄清一下,上面的实现是受此启发的 blog post

    但是我们也有在循环中创建的函数的其他实例。

    到目前为止,唯一的解决方法是从jslint中排除这些JS文件,但是我们希望使用jslint进行代码验证和语法检查,作为我们持续集成和构建工作流的一部分。

    6 回复  |  直到 8 年前
        1
  •  66
  •   havlock    7 年前

    Douglas Crockford有一种新的惯用方法来实现上述功能—他的旧技术是使用内部函数来绑定变量,但新技术使用函数生成器。看到了吗 slide 74 in the slides to his "Function the Ultimate" talk . [此幻灯片已不存在]

    对于懒惰的人,以下是代码:

    function make_handler(div_id) {
        return function () {
            alert(div_id);
        };
    }
    for (i ...) {
        div_id = divs[i].id;
        divs[i].onclick = make_handler(div_id);
    }
    
        2
  •  12
  •   Community pid    7 年前

    (这个问题发布几个月后我才偶然发现……)

    如果函数实际上是在迭代中分配给不同值(或在迭代中生成的对象)的同一个函数,则需要将函数分配给命名变量,并在循环中使用赋值中函数的奇异实例:

    handler = function (div_id) {
        return function() { alert(div_id); }
    }
    
    for (i ...) {
        div_id = divs[i].id;
        divs[i].onclick = handler(div_id);
    }
    

    当我在这里提出一个类似的关于堆栈溢出的问题时,其他比我聪明的人对此进行了更多的评论/讨论: JSlint error 'Don't make functions within a loop.' leads to question about Javascript itself

    是的,它是教条式的和惯用的。也就是说,这通常是“对的”——我发现许多对JSLint持否定态度的人实际上并不理解Javascript的精妙之处,因为Javascript很多而且迟钝。

        3
  •  11
  •   lifebalance    8 年前

    从字面上说,得到 围绕 通过执行以下操作来解决问题:

    1. 创建 .jshintrc 文件
    2. 将以下行添加到 文件

      {"loopfunc" : true, // tolerate functions being defined in loops }

        4
  •  7
  •   Evan Trimboli    14 年前

    JSLint只是一个指南,您不必总是遵守规则。问题是,你不是在循环中创建它所指的函数。在应用程序中只创建一次类,而不是一次又一次。

        5
  •  5
  •   jevon JesseBuesking    13 年前

    如果您使用的是JQuery,则可能需要在循环中执行以下操作:

    for (var i = 0; i < 100; i++) {
      $("#button").click(function() {
        alert(i);
      });
    }
    

    为了满足JSLint的要求,解决这个问题的一种方法是(在jquery1.4.3+中)使用额外的handler data参数 .click() :

    function new_function(e) {
      var data = e.data; // from handler
      alert(data); // do whatever
    }
    
    for (var i = 0; i < 100; i++) {
      $("#button").click(i, new_function);
    }
    
        6
  •  3
  •   TheCarver    8 年前

    只需移动您的:

    (function (name, func) {...})()

    从循环中删除并将其赋给变量,如:

    var makeFn = function(name, func){...};

    然后在循环中:

    prototype[prop] = makeFn(...)