处理循环变量的重复声明警告

时间:2012-05-29 15:03:07

标签: javascript jslint

请考虑以下代码:

for (var i=0; i<100; i++) {
    // your code here
}
// some other code here
for (var i=0; i<500; i++) {
    // custom code here
}

任何体面的lint工具(jslint,jshint或内置的IDE)都会告诉警告 - duplicate declaration of variable i。这可以通过使用具有其他名称(kj)的变量或将声明移到顶部来解决:

var i; // iterator
for (i=0; i<100; i++) {}
for (i=0; i<500; i++) {}

我不喜欢这两种变体 - 我通常不会在顶部做声明(即使我做了,我也不希望看到辅助变量 - ij,{ {1}})并且在这些示例中实际上没有什么不好的地方可以更改变量的名称。

虽然我确实想要一个巨大的警告,以防我这样写:

k

您对此类案件的处理方法是什么?

5 个答案:

答案 0 :(得分:47)

JavaScript有许多结构,看起来像其他计算机语言中众所周知的结构。 JavaScript以其他大多数计算机语言的方式解释另一种方式的构造是危险的。

如果不了解JavaScript的人(顺便说一下常见情况)会看到像

这样的结构
for (var i=0; i<100; i++) {
    // your code here
}

或看到块中变量的声明

{
    var i;
    //some code
    {
        var j;
        // some code
    }
}

然后大多数读者会认为将定义块级变量。 JavaScript没有块级变量。所有变量都将被解释为定义的函数级别。

所以我永远不会在代码中定义变量,如果代码不仅仅是一些只会写5分钟的测试代码。主要原因是我不想编写代码并使用可能被误解的语言结构

顺便说一句,JSLint发现块内部变量的定义如此糟糕,以至于它停止了代码分析的处理。没有可以改变此行为的JSLint选项。我发现JSLint的行为不好,但我同意for循环中的变量声明是错误的,因为大多数人都会将其读作带有 local 循环变量的代码,这是不正确。

如果您使用

for (var i=0; i<100; i++) {
    // your code here
}
// some other code here
for (var i=0; i<500; i++) {
    // custom code here
}

然后JavaScript为您移动 function 开头的所有变量声明。所以代码将是

var i = undefined, i = undefined; // duplicate declaration which will be reduced
                                  // to one var i = undefined;

for (i=0; i<100; i++) {
    // your code here
}
// some other code here
for (i=0; i<500; i++) {
    // custom code here
}

所以请考虑其他读者的代码。不要使用任何可能以错误方式解释的结构。

答案 1 :(得分:18)

let关键字是在javascript 1.7中引入的。请查找MDN文档here

var内替换letfor loop解决了问题,现在可以在循环范围内声明局部变量。在这里查看stackoverlow社区说明:What's the difference between using "let" and "var" to declare a variable?

未来的代码:

for (let i = 0; i < someVar.length; i++) {
    // do your thing here
}

答案 2 :(得分:6)

我建议将循环封闭在自动执行的函数中,这些函数的名称告诉你循环正在做什么。这有效地为循环提供了块范围。例如:

var users = response['users']
;(function appendUsers(){
    for (var i = 0; i < users.length; i++) {
        var user      = users[i]
        var userEmail = user['email']
        var userId    = user['id']
        /* etc */ 
    }
})() // appendUsers

如果你这样做:

var i
for (i = 0; i < someVar.length; i++) {
    for (i = 0; i < someOtherVar.length; i++) {
        // This is a bug that a validator will not notice.
    }
}

另一方面:

for (var i = 0; i < someVar.length; i++) {
    for (var i = 0; i < someOtherVar.length; i++) {
        // This is a bug that a validator will warn you about.
    }
}
for (var i = 0; i < yetAnotherVar.length; i++) {
    // It will also warn you about this, but so what?
}

您可以停止使用i作为迭代器:

for (var companyIndex = 0; companyIndex < companies.length; companyIndex++) {
    var company = companies[companyIndex]
}

如果您还在使用jQuery,可以使用其jQuery.each()方法:

$.each(someVar, function(i, value){
    // etc
})

如果您希望使用IE8及更早版本,则无法使用Array.prototype.forEach(),除非您添加Polyfill code或类似内容。

答案 3 :(得分:2)

我倾向于使用数组内置函数,例如map,filter和forEach,从而完全避免了这个问题。这也会自动为您提供范围循环体,这也非常有用。

如果使用那些与用例不符,我通常会采用顶级声明,这样我就可以避免你提到的问题。

答案 4 :(得分:1)

这里的最佳做法应该是良好的编程风格:

程序应该用简短的函数构造,这将完成一项小任务。 通常情况下,如果你正在循环,你会做一些特殊的东西,它应该代表一个自己的功能。 最后,每个函数都有自己的作用域,因此复制声明问题就不存在了。

function myApp() {
    magicLoopAction();
    someOtherMagicStuff();
}
function magicLoopAction() {
    for (var i = 0; i < 42; i++) { 
        // whoopwhoop
    }
}
function someOtherMagicStuff() {
    for (var i = 0; i < 69; i++) { 
        // lint is happy and proud on you
    }
}