警告: 问题仍然适用于循环的for…不要使用for…in来迭代数组,而是使用它来迭代 对象的属性。也就是说,这个


我知道JavaScript语法中的基本for是这样的:

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

当前回答

在每个人发布的非常好的答案之上,我想补充的是,性能最好的解决方案是ES6条目。对于这里的许多开发者来说,这似乎是一种禁忌,所以我创建了这个perf benchamrk。

它要快6倍。主要是因为不需要:a)访问数组不止一次,b)强制转换索引。

其他回答

在ES6中,使用for…的循环。 你可以在…就像这样

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

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

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。条目,现在支持跨当前浏览器版本:

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

然而,对于一般的迭代对象(你会使用For…of循环而不是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);
}

demo

如果您在枚举属性时确实是指…,那么您将需要一个额外的计数器。种(obj)。forEach可以工作,但它只包括自己的属性;in包含原型链上任意位置的可枚举属性。

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

Array1 = ['a', 'b', 'c'] 对于(数组1的元素){ console.log(array1.indexOf(element), element) // 0 a 1 b 2 c .log(array1.indexOf(element), element }

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

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

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 }

在每个人发布的非常好的答案之上,我想补充的是,性能最好的解决方案是ES6条目。对于这里的许多开发者来说,这似乎是一种禁忌,所以我创建了这个perf benchamrk。

它要快6倍。主要是因为不需要:a)访问数组不止一次,b)强制转换索引。