【问题标题】:difference between for loop and for-in loop in javascriptjavascript中for循环和for-in循环的区别
【发布时间】:2015-02-25 07:23:49
【问题描述】:

我发现javascript中的for循环和for-in循环是有区别的。

当我定义一个新数组时:

var a=new Array();

然后我将一些值放入但不是连续的,例如:

a[0]=0;a[1]=1;a[4]=4; 

当我使用for(i=0;i<5;i++) 获取值并使用alert 显示它时,它与使用for(i in a) 不同。

前一个将显示索引 2,3 中显示“未定义”的元素,而 for-in 将仅显示索引 0,1 和 4。谁能告诉我为什么?

【问题讨论】:

  • 是的,它们用于不同的目的。另外,你有一些问题,你忘了var,你应该使用[] 而不是new Array,JS 中的稀疏数组不是好的做法。
  • JavaScript 数组是类似列表的对象,而不是典型的数组。
  • JavaScript for...in vs for 的可能重复项

标签: javascript arrays for-loop for-in-loop


【解决方案1】:

for (... in ...) 通常用于遍历对象的属性(JavaScript 用于关联数组),而典型的for 循环用于顺序数组。

在您的示例中,您实际上是在创建一个具有键 0、1 和 4 的关联数组。如果您想要一个真正的 JavaScript 数组,您可以使用 a.push(0)a.push(1) 等...将值按顺序添加到数组的末尾。

对于顺序数组,语法for (var i = 0; i < arr.length; i++) 使i 从0 计数到小于数组长度的1。这将允许i 与数组中的每个索引一一相等,从而允许您访问该数组中的每个元素。

但是,对于关联数组,键是非顺序的,因此使变量计数“从 0 到 1 小于数组的长度”不会产生所需的结果。在您的示例中,它接近工作了,因为您手动创建的键恰好是 0、1 和 4,它们几乎是连续的。

如果您想要一个具有非连续键的数组——“不连续”,如 0、1、4 等——您可能应该使用对象,而不是数组,例如

var obj = {};
obj[0] = 0;
obj[1] = 1;
obj[4] = 4;

然后使用for (... in ...) 循环将是正确的语法。

【讨论】:

    【解决方案2】:

    For 循环遍历它们,直到 i 达到 5,因此 i = 0,1,2,3,4,5 并遍历所有。但是使用 for...in 循环迭代它们的属性不仅不是 0 到 5,而是您定义的 0,1,4。

    来自MDN

    注意: for..in 不应用于迭代索引顺序很重要的数组。

    数组索引只是具有整数名称的可枚举属性,在其他方面与一般对象属性相同。无法保证 for...in 会以任何特定顺序返回索引,并且会返回所有可枚举属性,包括具有非整数名称的属性和继承的属性。

    因为迭代的顺序取决于实现,所以迭代数组可能不会以一致的顺序访问元素。因此,在遍历访问顺序很重要的数组时,最好使用带有数字索引的 for 循环(或 Array.forEach 或 for...of 循环)。

    【讨论】:

      【解决方案3】:

      for-in 循环枚举变量的可枚举属性。对于您的数组,“0”、“1”和“4”被添加为数组上的可枚举属性。因此,for-in 循环只能在 "i" 中得到 0、1 和 4。

      for 循环适用于 i = 0 到 5。因此您尝试访问 2 和 3 处的值,这显然是未定义的。

      【讨论】:

        【解决方案4】:

        语法

        for (var k in obj)

        实际上是一个 for-each 循环。它遍历对象的属性。您应该熟悉 JavaScript 对象。对象是键到值的映射。

        因此,for-each 循环对对象非常有用。但是,在遍历数组时,最好使用常规的 for 循环。

        下面是一个用于对象属性的 for-each 循环示例: http://jsfiddle.net/nbtLpw0z/.

        【讨论】:

          【解决方案5】:

          我使用 for-in 循环是因为它是一种较短的形式,但有时您可能希望控制迭代变量。例如,如果要遍历偶数索引,则需要使用普通的 for 循环:

          for (var i = 0; i < myarray.length; i+=1) {...}
          

          这同样适用,例如,如果您想向后迭代:

          for (var i = myarray.length-1; i >= 0; i--) {...}
          

          当然,对于对象,for-in 循环允许您在迭代变量中获取属性名称。例如。

           var obj = {year: 2014, city: "Surat"}
           for (var propn in obj) alert(propn + " = " + obj[propn]);
          

          在您的示例中,我会使用 for-in 因为您正在进行简单的迭代。此外,我认为在未优化的 Javascript 编译器/解释器中,for-in 循环会更快,因为变量增量是在内部完成的。

          【讨论】:

            【解决方案6】:

            对于初学者来说,在数组上使用for in 循环是没有意义的,因为 JavaScript 中的数组只能有有序的数字索引。因此,您可以在0array.length - 1 范围之间的任何索引处访问数组 唉,如果您想使用 for in 循环来遍历数组,您当然可以,但是,常规的 for 循环更合适。

            for in 循环在您没有有序数字索引时使用。 JavaScript 对象实际上是一个有序的哈希表。您可以使用 in 运算符访问 JavaScript 对象的键,该运算符返回对象的键,通过访问该键的对象,您可以获得值。

            例如:

            var obj = {
               hello: "world",
               world: "hello"
            };
            

            常规的 for 循环不起作用,因此您不需要使用 for in 循环。

            for(var i in obj) console.log(obj[i]);
            

            对象也不会返回足够精确的长度属性来迭代整个对象,因此for in 循环是绝对必要的。

            另请注意,如果不按照下一个空闲元素存在的顺序为数组分配值,则会自动将 undefined 放置在您跳过的元素中。

            在您的示例中,数组如下所示:

            [0, 1, undefined × 2, 4]
            

            【讨论】:

              【解决方案7】:

              for-each 循环被推荐用于遍历对象属性,而for 循环被推荐用于数组。在您的情况下,您可以使用 push() 获得相同的结果。

              var a = []; //recommended way of declaring arrays over `new Arrays()`
              a.push(0);
              a.push(1);
              a.push(4);
              //usual for-loop
              for (var i = 0; a.length > i; i++) //recommended
                console.log('a[', i, ']=', a[i]);
              console.log('---------------------');
              // for-each loop
              for (var k in a) //not recommended
                console.log('a[', k, ']=', a[k]);
              console.log('---------------------');
              Open console...

              var person = {
                'name': 'Adam'
              };
              
              for (var k in person)
                console.log('person.' + k, '=', person[k]);
              console.log('----------------------');
              
              person.age = 26; //new property
              
              for (var k in person)
                console.log('person.' + k, '=', person[k]);
              console.log('----------------------');
              
              person['gender'] = 'Male'; //again a new property
              
              for (var k in person)
                console.log('person.' + k, '=', person[k]);
              console.log('----------------------');
              
              person.name = 'Will'; //updating property
              
              for (var k in person)
                console.log('person.' + k, '=', person[k]);
              console.log('----------------------');
              Open console...

              【讨论】:

                【解决方案8】:

                在底层,for-in 循环只不过是一个 for 循环。 For(i in x) 分解为 -

                for(i=0;i<x.length;i++) {
                if(x[i] != undefined)
                console.log(x[i]);
                }
                

                【讨论】:

                  【解决方案9】:

                  我已经阅读并听说正常的 for 循环:for(var i = 0; i &lt; arr.length; i++) 更快。但我会说使用for of:

                  var arr = [1,2,3], obj = {x: 1, y:2};
                  for(var value of arr) console.log(value) // 1, 2, 3
                  for(var key in obj) console.log(key) // x, y
                  for(var key of Object.keys(obj)) console.log(key) // x, y
                  

                  您可以使用Object.keys(obj) 将对象的键转换为数组并在其上调用Array.prototype 方法

                  【讨论】:

                    【解决方案10】:

                    您的“for”循环会查看从 0 到 4 的数组索引的所有值,因为这正是您要求它执行的操作。所以它查看 a[0] 并找到一个值,然后是 a[1](同样的交易),然后它转到 a[2] 并意识到您从未为 a[2] 初始化一个值,因此它是未定义的. a[3] 也是如此,最后 a[4] 有一个值,所以它会找到它。

                    这种类型的“for”循环会检查每个索引是否定义。

                    “for ... in ...”循环只会检查初始化值。您的数组有 3 个已初始化的值,因此它会检查这些值。它会按照索引的顺序向您显示它们,但索引实际上并不影响它正在查看的内容。因此,如果您将“a[1]”更改为“a[3]”并将“a[4]”更改为“a[10]”,当您使用“for .. . in ..." 循环。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2017-01-05
                      • 1970-01-01
                      • 2011-07-12
                      • 2021-09-17
                      • 1970-01-01
                      • 2012-08-30
                      • 2019-10-01
                      • 2011-02-11
                      相关资源
                      最近更新 更多