488

警告:

问题仍然适用于for…of循环。> 不要for…in用来迭代Array,用它来迭代对象的属性。也就是说,这


我了解for…inJavaScript 中的基本语法如下所示:

for (var obj in myArray) {
    // ...
}

但是我如何获得循环计数器/索引

我知道我可能会做类似的事情:

var i = 0;
for (var obj in myArray) {
    alert(i)
    i++
}

甚至是老好人:

for (var i = 0; i < myArray.length; i++) {
    var obj = myArray[i]
    alert(i)
}

但我宁愿使用更简单的for-in循环。我认为它们看起来更好,更有意义。

有没有更简单或更优雅的方法?


在 Python 中很容易:

for i, obj in enumerate(myArray):
    print i
4

13 回答 13

824

for…in迭代属性名称,而不是值,并且以未指定的顺序进行(是的,即使在 ES6 之后)。您不应该使用它来迭代数组。对于他们来说,有 ES5 的forEach方法可以将值和索引都传递给你给它的函数:

var myArray = [123, 15, 187, 32];

myArray.forEach(function (value, i) {
    console.log('%d: %s', i, value);
});

// Outputs:
// 0: 123
// 1: 15
// 2: 187
// 3: 32

或者 ES6 的Array.prototype.entries,现在支持当前浏览器版本:

for (const [i, value] of myArray.entries()) {
    console.log('%d: %s', i, value);
}

对于一般的可迭代对象(您将使用for…of循环而不是 a for…in),没有任何内置的,但是:

function* enumerate(iterable) {
    let i = 0;

    for (const x of iterable) {
        yield [i, x];
        i++;
    }
}

for (const [i, obj] of enumerate(myArray)) {
    console.log(i, obj);
}

演示

如果您确实是指for…in枚举属性 – 您将需要一个额外的计数器。Object.keys(obj).forEach可以工作,但它只包括自己的属性;for…in包括原型链上任何地方的可枚举属性。

于 2012-04-16T18:49:16.917 回答
296

在 ES6 中,最好使用for... of循环。for... of您可以像这样获取索引

for (let [index, val] of array.entries()) {
  // your code goes here    
}

请注意,它Array.entries()返回一个迭代器,这使得它可以在 for-of 循​​环中工作;不要将此与Object.entries()混淆,后者返回一个键值对数组。

于 2016-12-19T11:17:43.253 回答
45

这个怎么样

let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))

array.forEach此方法有一个index参数,该参数是数组中正在处理的当前元素的索引。

于 2018-02-10T04:17:42.677 回答
23

小数组集合的解决方案:

for (var obj in arr) {
    var i = Object.keys(arr).indexOf(obj);
}

arr - ARRAY, obj - 当前元素的 KEY, i - COUNTER/INDEX

注意:方法keys()不适用于 IE 版本 <9,您应该使用Polyfill代码。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

于 2015-01-12T09:36:00.010 回答
15

For-in-loops 遍历对象的属性。不要将它们用于数组,即使它们有时会起作用。

对象属性没有索引,它们都是相等的,不需要按确定的顺序运行。如果您想计算属性,则必须设置额外的计数器(就像您在第一个示例中所做的那样)。

循环数组:

var a = [];
for (var i=0; i<a.length; i++) {
    i // is the index
    a[i] // is the item
}

循环对象:

var o = {};
for (var prop in o) {
    prop // is the property name
    o[prop] // is the property value - the item
}
于 2012-04-16T18:49:22.730 回答
11

正如其他人所说,您不应该使用 for..in 来遍历数组。

for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }

如果你想要更简洁的语法,你可以使用 forEach:

myArray.forEach( function ( val, i ) { ... } );

如果要使用此方法,请确保包含 ES5 shim 以添加对旧浏览器的支持。

于 2012-04-16T18:55:37.170 回答
6

rushUp给出的答案是正确的,但这会更方便

for (let [index, val] of array.entries() || []) {
   // your code goes here    
}
于 2020-04-13T12:29:57.853 回答
2

除了每个人都发布的非常好的答案之外,我想补充一点,性能最高的解决方案是 ES6 entries。对于这里的许多开发人员来说,这似乎是矛盾的,所以我创建了这个 perf benchamrk

在此处输入图像描述

它快了约 6 倍。主要是因为不需要:a)多次访问数组,b)转换索引。

于 2020-04-22T09:17:08.880 回答
1

这是一个eachWithIndex适用于任何可迭代的函数。

您还可以编写一个类似的函数eachWithKey,使用for...in.

// example generator (returns an iterator that can only be iterated once)
function* eachFromTo(start, end) { for (let i = start; i <= end; i++) yield i }

// convers an iterable to an array (potential infinite loop)
function eachToArray(iterable) {
    const result = []
    for (const val of iterable) result.push(val)
    return result
}

// yields every value and index of an iterable (array, generator, ...)
function* eachWithIndex(iterable) {
    const shared = new Array(2)
    shared[1] = 0
    for (shared[0] of iterable) {
        yield shared
        shared[1]++
    }
}

console.log('iterate values and indexes from a generator')
for (const [val, i] of eachWithIndex(eachFromTo(10, 13))) console.log(val, i)

console.log('create an array')
const anArray = eachToArray(eachFromTo(10, 13))
console.log(anArray)

console.log('iterate values and indexes from an array')
for (const [val, i] of eachWithIndex(anArray)) console.log(val, i)

生成器的好处是它们很懒,可以将另一个生成器的结果作为参数。

于 2019-01-24T14:13:42.923 回答
1

这是我的复合迭代器版本,它产生一个索引和任何传递的生成器函数的值,并带有一个(慢)素数搜索的例子:

const eachWithIndex = (iterable) => {
  return {
    *[Symbol.iterator]() {
      let i = 0
      for(let val of iteratable) {
        i++
          yield [i, val]
      }
    }
  }

}

const isPrime = (n) => {
  for (i = 2; i < Math.floor(Math.sqrt(n) + 1); i++) {
    if (n % i == 0) {
      return false
    }
  }
  return true
}

let primes = {
  *[Symbol.iterator]() {
    let candidate = 2
    while (true) {
      if (isPrime(candidate)) yield candidate
        candidate++
    }
  }
}

for (const [i, prime] of eachWithIndex(primes)) {
  console.log(i, prime)
  if (i === 100) break
}

于 2019-03-04T11:09:39.540 回答
1

要在数组上使用 for..of 循环并检索索引,您可以使用array1.indexOf(element)它将返回循环中元素的索引值。您可以使用此方法返回索引和值。

array1 = ['a', 'b', 'c']
for (element of array1) {
    console.log(array1.indexOf(element), element) // 0 a 1 b 2 c
}

正如评论中提到的,当数组包含非唯一值时,这将返回错误索引。(考虑到 arr = ['a', 'b', 'c', 'a'],arr[3] 的索引将返回 0 而不是 3)

于 2020-06-23T07:40:54.943 回答
0

通过 js 中的 for of 循环系统,你可以找到所有索引为 no 的数组元素...

const menus = ['Bengali', 'Italiano', 'Americano', 'Thai', 'Chinese'];

for (const menus of menu.entries()) {
console.log(menus);
}
于 2022-02-18T06:23:58.547 回答
0

在这种情况下,使用简单的枚举函数来获得满意的答案。

var = [100, 254, 3, 55]
for a in enumerate(var):
print(a)

输出:

(0, 100)
(1, 254)
(2, 3)
(3, 55)
于 2022-03-05T11:21:12.370 回答