如何解决jslint错误“不要在一个循环内的function”?

我正在努力使所有的JS代码通过jslint传递,有时会用很多的选项来调整,以获得遗留代码传递,以便稍后修复它。

有一件事是jslint抱怨我没有一个workround。 那就是当使用像这样的结构时,我们得到错误'不要在一个循环内做function。

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

此循环是经典inheritance的JS实现的一部分,其中扩展现有类的类在调用扩展类的成员时保留扩展类的超级属性。 只是为了澄清,上面的实现是由John Resig这篇博文的启发。

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

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

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

道格拉斯·克罗克福德(Douglas Crockford)有一种新的惯用的方法来达到上述目的 – 他的旧技术是使用内部函数来约束variables,但是新技术使用函数的制造者。 请参阅幻灯片中的幻灯片74,以阅读“function最终”的演讲 。 [这个slideshare不再存在]

对于懒惰,这里是代码:

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

(在发布后的几个月里,我就偶然发现了这个问题)

如果在一个循环中创build一个函数,则为该循环的每次迭代创build一个函数的实例。 除非每个迭代的函数实际上不同,否则使用将函数发生器放在循环之外的方法 – 这样做不仅仅是Crockery,它让其他读你的代码的人知道这是你的意图。

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

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

关于这个的更好的评论/讨论是由其他人比我更聪明,当我在堆栈溢出提出类似的问题: JSlint错误“不要在循环内的function”。 导致关于Javascript本身的问题

至于JSLint:是的,这是教条式和惯用的。 也就是说,这通常是“正确的” – 我发现许多对JSLint发出负面消息的人实际上并不了解JavaScript的细微之处,而这些微妙的东西很多。

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

  1. 创build一个.jshintrc文件
  2. .jshintrc添加到.jshintrc文件中

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

JSLint只是一个指导,你并不总是要遵守规则。 事情是,你不是在循环中创build函数,而是指它所指的。 你只在你的应用程序中创build你的类,而不是一次又一次地创build你的类。

如果你正在使用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); } 

只要移动你的:

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

阻止循环并将其分配给variables,如:

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

然后在循环中有:

prototype[prop] = makeFn(...)