如何解决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的细微之处,而这些微妙的东西很多。
从字面上看,通过执行以下操作来解决问题:
- 创build一个
.jshintrc
文件 -
.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(...)