代码之家  ›  专栏  ›  技术社区  ›  TimG

在多个for循环中使用相同的变量名是不是一种糟糕的做法?

  •  63
  • TimG  · 技术社区  · 12 年前

    我只是在使用JSHint编写一些JavaScript代码。在代码中,我有两个for循环,它们都是这样使用的:

    for (var i = 0; i < somevalue; i++) { ... }
    

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

    现在,JSHint向我显示了第二个for循环的错误:“'i'已经定义好了”。我不能说这不是真的(因为这显然是真的),但我一直认为这无关紧要,因为var I只在特定的地方使用。

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

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

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

    JSLint btw.在第一个for循环时停止验证,因为我没有在函数的顶部定义vari(这就是我最初切换到JSHint的原因)。因此,根据这个问题中的例子: Should I use JSLint or JSHint JavaScript validation? 无论如何,我应该使用这样的for循环来确认JSLint:

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

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

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

    那么,有没有最佳实践呢?或者我可以只使用上面的任何代码,这意味着我选择“我的”最佳实践?

    6 回复  |  直到 2 年前
        1
  •  60
  •   starball Martin Jorgensen    2 年前

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

    以下代码。。。

    for (var i = 0; i < 10; i++) {}
    for (var i = 5; i < 15; i++) {}
    

    …被有效地解释为:

    var i;
    for (i = 0; i < 10; i++) {}
    for (i = 5; i < 15; i++) {}
    

    请注意,实际上只有一个声明 i ,以及对它的多次赋值-您不能真正在同一范围内“重新声明”一个变量。

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

    有最佳实践吗?或者我可以使用上面的任何代码吗?

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

    但是,正如您所观察到的,无论采用何种方法,代码都可以工作,因此这是一种风格/惯例的选择,您可以使用您觉得最舒服的任何形式。

        2
  •  8
  •   Community CDub    8 年前

    它只在 the comment by @TSCrowder :如果您的环境支持它(Firefox、Node.js),那么在ES6中您可以使用 let declaration

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

    哪一个 将范围限制在for循环内 额外奖励:JSHint停止抱怨。

        3
  •  6
  •   Jashwant    12 年前

    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.
    }
    
        4
  •  5
  •   Corneliu    12 年前

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

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

    这个 允许 关键字包含在ECMAScript 6规范中。

        5
  •  4
  •   serv-inc    9 年前

    我知道这个问题已经得到了回答,但如果你想要超级for循环,可以这样写:

    var names = ['alex','john','paul','nemo'],
        name = '',
        idx = 0,
        len = names.length;
    
    for(;idx<len;++idx)
    {
        name = names[idx];
        // do processing...
    }
    

    这里发生了几件事。。。

    1. 数组长度存储在 len 。这将停止JS评估 names.length 每次迭代

    2. 这个 idx 增量是预增量(例如++idx NOT idx++)。预增量在本机上比后增量快。

    3. 存储对的引用 name 。这是可选的,但如果您要使用 名称 变量很大。每次呼叫 names[idx] 需要在数组中查找索引。无论这种搜索是线性搜索、树搜索还是哈希表,查找仍在进行。因此,将引用存储在另一个变量中以减少查找。

    最后,这只是我个人的偏好,我没有任何证据或任何性能优势。然而,我总是喜欢将变量初始化为它们将要成为的类型。 name = '', .

        6
  •  1
  •   Nikolay Kostov    9 年前

    最佳实践是减少变量的范围,因此为循环声明迭代变量的最佳方式是

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

    我知道用声明的变量的范围 var 但我在这里考虑的是代码的可读性。