在多个for循环中使用相同的变量名是不好的做法吗?

Tim*_*imG 61 javascript for-loop jslint jshint

我只是使用JSHint来绘制一些JavaScript代码.在代码中我有两个for循环,这两个使用如下:

for (var i = 0; i < somevalue; i++) { ... }
Run Code Online (Sandbox Code Playgroud)

因此,两个for循环都使用var i进行迭代.

现在JSHint向我展示了第二个for循环的错误:"'我'已经定义了".我不能说这不是真的(因为它显然是)但我一直认为这无关紧要因为var i仅用于那个特定的地方.

以这种方式使用for循环是不好的做法吗?我应该在我的代码中为每个for循环使用不同的变量

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }
Run Code Online (Sandbox Code Playgroud)

或者这是我可以忽略的错误(因为它不会破坏我的代码,它仍然会做它应该做的事情)?

JSLint顺便说一下.停止在第一个for循环验证,因为我没有在函数的顶部定义var i(这就是我首先切换到JSHint的原因).所以根据这个问题的例子:我应该使用JSLint还是JSHint JavaScript验证? - 无论如何我应该使用像这样的for循环来确认JSLint:

...
var i;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
...
//for-loop 2
for (i = 0; ...; i++) { ... }
Run Code Online (Sandbox Code Playgroud)

这对我来说也很好看,因为这样我应该避免JSLint和JSHint中的错误.但我不确定的是,我是否应该为每个for循环使用不同的变量,如下所示:

...
var i, j;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
//for-loop 2
for (j = 0; ...; j++) { ... }
Run Code Online (Sandbox Code Playgroud)

那么这是最佳实践还是我可以选择上面的任何代码,这意味着我选择"我的"最佳实践?

Jam*_*ice 58

由于变量声明被提升到它们出现的范围的顶部,因此解释器将以相同的方式有效地解释两个版本.出于这个原因,JSHint和JSLint建议将声明移出循环初始化器.

以下代码......

for (var i = 0; i < 10; i++) {}
for (var i = 5; i < 15; i++) {}
Run Code Online (Sandbox Code Playgroud)

......有效地解释为:

var i;
for (i = 0; i < 10; i++) {}
for (i = 5; i < 15; i++) {}
Run Code Online (Sandbox Code Playgroud)

请注意,实际上只有一个声明i和多个赋值 - 您无法真正"重新声明"同一范围内的变量.

要真正回答你的问题......

有没有最好的做法,或者我可以使用上面的任何代码?

关于如何最好地处理这个问题,有不同的意见.就个人而言,我同意JSLint,并认为当您在每个范围的顶部声明所有变量时代码更清晰.既然这就是代码的解释方式,为什么不编写看起来像它的行为的代码呢?

但是,正如您所观察到的那样,无论采用何种方法,代码都能正常工作,因此这是一种风格/惯例选择,您可以使用您认为最舒适的形式.

  • 我认为我最喜欢这种方法,因为当你说"为什么不编写看起来像它的行为的代码?"时,我同意你的意思.它非常清晰可读.我想我会擅长这种风格. (4认同)
  • 我宁愿在我的循环头中声明我的循环迭代器,因为它使得变量用于什么非常明显,因为循环迭代器是历史上简单的非描述性名称,例如`i`和`j`.你应该如何避免使用相同的变量作为多个循环的迭代器的问题.**不要为多个循环使用与迭代器相同的变量.**声明多个迭代器变量或不在同一个块中执行多个循环.我个人认为如果你将每个循环分解为自己的辅助函数,它最具可读性,那么你可以在两者中使用`i`. (2认同)

Jas*_*ant 6

javascript中的变量是函数作用域(不是块作用域).

当你var i在循环中定义时,它仍然在循环中,也在具有该循环的函数中.

见下文,

function myfun() {
    //for-loop 1
    for (var i = 0; ...; i++) { ... }

    // i is already defined, its scope is visible outside of the loop1.
    // so you should do something like this in second loop.

    for (i = 0; ...; j++) { ... }

    // But doing such will be inappropriate, as you will need to remember
    // if `i` has been defined already or not. If not, the `i` would be global variable.
}
Run Code Online (Sandbox Code Playgroud)

  • 但在这种情况下,如果第一个循环被删除,第二个循环最终会将"i"泄漏到全局范围.但是,如果您使用的是linter,则不应该提交此错误. (2认同)

ser*_*inc 6

它只在@TSCrowder的评论中提到:如果您的环境支持它(Firefox,Node.js),在ES6中您可以使用let声明

//for-loop 1
for (let i = 0; ...; i++) { ... }

//for-loop 2
for (let i = 0; ...; i++) { ... }
Run Code Online (Sandbox Code Playgroud)

将范围限制在for循环中.额外奖励:JSHint停止抱怨.


Cor*_*liu 5

JSHint 显示错误的原因是因为在 JS 中变量作用域是函数,并且变量声明被提升到函数的顶部。

在 Firefox 中,您可以使用let关键字来定义块范围,但其他浏览器目前不支持。

let关键字包含在 ECMAScript 6 规范中。