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

Ily*_*yev 47 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
}
Run Code Online (Sandbox Code Playgroud)

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

var i; // iterator
for (i=0; i<100; i++) {}
for (i=0; i<500; i++) {}
Run Code Online (Sandbox Code Playgroud)

我不喜欢这两个变种-我不顶部做出的声明通常(即使我做了我不希望看到有辅助变量- ,i,j)k真的没什么不好在这些例子事情改变的变量'的名字.

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

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

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

Ole*_*leg 48

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

如果一个不太了解JavaScript的人(顺便说一下常见的情况)就会看到这样的结构

for (var i=0; i<100; i++) {
    // your code here
}
Run Code Online (Sandbox Code Playgroud)

或者看到块中变量的声明

{
    var i;
    //some code
    {
        var j;
        // some code
    }
}
Run Code Online (Sandbox Code Playgroud)

那么大多数读者会认为会定义块级变量.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
}
Run Code Online (Sandbox Code Playgroud)

然后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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 那么处理循环'i'声明的双重处理的正确方法是什么? (13认同)
  • `for(var i = 0; i <someVar.length; i ++){}`怎么可能被人们误解?它没有任何含糊之处.你可以"误解"它的唯一方法就是你认为JavaScript有阻止范围.您的建议不是编写可理解代码的优点的实例,也不是接受当前JavaScript版本规则的实例.这是为了给无知的程序员提供JavaScript具有块范围的印象; 没有其他理由这样写.它的唯一目的是误导人们JavaScript的工作原理. (10认同)
  • 这不是对*代码*的误解,而是对*语言*的误解.如果程序员认为JS的工作方式与实际工作方式不同,那么正确的解决方案就是教会他们语言的实际工作方式.一个人不采用编程风格的唯一目的是允许人们继续误解语言的工作原理. (5认同)
  • @Hoto:**不要在`for`**中使用`var i`.而不是在`function`的开头用`for`循环声明`var i`一次. (4认同)
  • 如果你有嵌套循环并且每个都使用`i`,那么你的方法会导致*更多*问题,而不是更少,因为验证器不会捕获错误.但是,如果每次使用`for(var i = 0; ...)`,典型的验证器会在嵌套循环中抱怨"重复声明",你会注意到这个问题.如果循环没有嵌套但只是在同一个函数中,它也会抱怨 - 但是这个警告只是为了通知你潜在的问题,它不是无效的代码.你最好不要被告知潜在的问题,这是你通过采用你的方法而失去的. (3认同)
  • 这个讨论明确的一件事是块范围的优点,这将使这成为一个非问题.要真正解决这个问题,采用的正确做法是将一个循环包含在闭包中.为此,JavaScript的更高版本添加了`Array.prototype.forEach()`,但IE7/IE8不支持此功能.jQuery添加了`jQuery.each()`,它适用于所有浏览器,但显然需要jQuery.如果您需要支持旧浏览器并且不想添加代码来启用闭包循环,则可以手动将循环包含在自执行函数中.请参阅下面的答案. (2认同)

Sai*_*lov 18

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

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

未来代码:

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


Vla*_*nea 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
Run Code Online (Sandbox Code Playgroud)

如果你这样做:

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

另一方面:

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?
}
Run Code Online (Sandbox Code Playgroud)

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

for (var companyIndex = 0; companyIndex < companies.length; companyIndex++) {
    var company = companies[companyIndex]
}
Run Code Online (Sandbox Code Playgroud)

如果你还在使用jQuery,你可以使用它的jQuery.each()方法:

$.each(someVar, function(i, value){
    // etc
})
Run Code Online (Sandbox Code Playgroud)

Array.prototype.forEach()除非您添加Polyfill代码或类似代码,否则您无法使用IE8及更早版本.