请考虑以下代码:
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
。这可以通过使用具有其他名称(k
,j
)的变量或将声明移到顶部来解决:
var i; // iterator
for (i=0; i<100; i++) {}
for (i=0; i<500; i++) {}
我不喜欢这两种变体 - 我通常不会在顶部做声明(即使我做了,我也不希望看到辅助变量 - i
,j
,{ {1}})并且在这些示例中实际上没有什么不好的地方可以更改变量的名称。
虽然我确实想要一个巨大的警告,以防我这样写:
k
您对此类案件的处理方法是什么?
答案 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
内替换let
到for 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
}
}