63

我正在努力使我们所有的 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的这篇博文启发的。

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

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

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

4

6 回答 6

67

道格拉斯·克罗克福德(Douglas Crockford)有一种新的惯用方式来实现上述目标 - 他的旧技术是使用内部函数来绑定变量,但新技术使用函数生成器。请参阅他的“Function the Ultimate”演讲幻灯片中的幻灯片 74。[此幻灯片不再存在]

对于懒人,这里是代码:

function make_handler(div_id) {
    return function () {
        alert(div_id);
    };
}
for (i ...) {
    div_id = divs[i].id;
    divs[i].onclick = make_handler(div_id);
}
于 2010-06-14T15:36:41.503 回答
13

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

如果您在循环中创建函数,则会为循环的每次迭代创建一个函数实例。除非每次迭代所创建的函数实际上都不同,否则请使用将函数生成器置于循环之外的方法——这样做不仅仅是陶器,它会让其他阅读你的代码的人知道这是你的意图.

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

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 错误“不要在循环中创建函数。” 引发关于 Javascript 本身的问题

至于 JSLint:是的,它是教条和惯用的。也就是说,它通常是“正确的”——我发现许多对 JSLint 发表负面看法的人实际上并不了解 Javascript 的(微妙之处),因为它们很多且晦涩难懂。

于 2011-01-21T12:14:30.010 回答
11

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

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

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

于 2016-10-15T15:11:43.883 回答
8

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

于 2010-06-14T13:40:54.707 回答
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);
}
于 2012-02-20T00:36:32.197 回答
3

只需移动您的:

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

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

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

然后在循环中有:

prototype[prop] = makeFn(...)

于 2010-06-14T15:31:19.293 回答