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

Dealing with duplicate declaration warning for loop variables

本文关键字:声明 警告 循环 变量 处理      更新时间:2023-09-26

请考虑以下代码:

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++) {}

我不喜欢这两种变体 - 我通常不会在顶部进行声明(即使我这样做了,我也不希望看到有辅助变量 - ijk),在这些示例中确实没有什么不好的事情来更改变量的名称。

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

for (var i=0; i<100; i++) {
    for (var i=0; i<500; i++) {} // now that's bad
}

你对这种情况有什么看法?

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声明是不好的,因为它会被大多数人读取为带有局部循环变量的代码,这是不正确的。

如果您使用

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 会为你移动函数开头的所有变量声明。所以代码将作为

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
}

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

let关键字是在JavaScript 1.7中引入的。请在此处找到 MDN 文档

var 替换为 for loop 内部的 let 解决了这个问题,现在可以在循环范围内声明局部变量。在这里查看stackoverlow社区解释:使用"let"和"var"来声明变量有什么区别?

未来的代码:

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

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

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 代码或类似代码。

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

如果使用这些与用例不匹配,我通常会求助于 top 声明,这样我就可以避免您提到的问题。