如何修复jslint错误'不要在循环中创建函数'。

时间:2010-06-14 13:33:22

标签: javascript jslint

我正在努力使我们的所有JS代码都通过jslint传递,有时需要进行大量的调整以获得遗留代码的选项,以便稍后正确修复它。

有一件事jslint抱怨说我没有工作。也就是说,当使用这样的结构时,我们会收到错误“不要在循环中创建函数”。

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实现的一部分,其中扩展现有类的类在调用扩展类的成员时保留扩展类的超级属性。 只是为了澄清,上面的实现受到了John Resig的blog post的启发。

但我们还在循环中创建了其他函数实例。

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

有没有更好的方法来实现这样的功能,还是有办法通过jslint调整这样的代码?

6 个答案:

答案 0 :(得分:65)

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);
}

答案 1 :(得分:12)

(我发布这个问题几个月后我偶然发现了这个问题......)

如果在循环中创建函数,则会为循环的每次迭代创建函数的实例。除非正在进行的函数实际上对于每次迭代都是不同的,否则使用将函数生成器放在循环之外的方法 - 这样做不仅仅是Crockery,它让其他阅读代码的人都知道这是你的意图

如果函数实际上是在迭代中(或迭代中生成的对象)将相同的函数分配给不同的值,那么您需要将该函数分配给命名变量,并使用该函数的单个实例。循环中的赋值:

handler = function (div_id) {
    return function() { alert(div_id); }
}

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

当我在Stack Overflow上提出类似的问题时,其他人比我更聪明,对此进行了更多的评论/讨论: JSlint error 'Don't make functions within a loop.' leads to question about Javascript itself

至于JSLint: 是的,这是教条和惯用语。也就是说,它通常是“正确的” - 我发现许多对JSLint负面发声的人实际上并不理解(微妙的)Javascript,这很多很麻烦。

答案 2 :(得分:10)

从字面上看,通过执行以下操作来解决问题:

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

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

答案 3 :(得分:7)

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

答案 4 :(得分:5)

如果您正在使用JQuery,您可能希望在循环中执行类似的操作:

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

为了满足JSLint,解决此问题的一种方法是(在JQuery 1.4.3+中)使用.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);
}

答案 5 :(得分:3)

移动你的:

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

阻止循环并将其分配给变量,例如:

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

然后在循环中有:

prototype[prop] = makeFn(...)