在 JavaScript 中使用 for...of 语法获取循环计数器/索引
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10179815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get loop counter/index using for…of syntax in JavaScript
提问by hobbes3
Caution:
question still applies to
for…of
loops.> Don't usefor…in
to iterate over an Array, use it to iterate over the propertiesof an object. That said, this
警告:
问题仍然适用于
for…of
循环。> 不要for…in
用于迭代Array,使用它来迭代对象的属性。话说这个
I understand that the basic for…in
syntax in JavaScript looks like this:
我了解for…in
JavaScript中的基本语法如下所示:
for (var obj in myArray) {
// ...
}
But how do I get the loop counter/index?
但是我如何获得循环计数器/索引?
I know I could probably do something like:
我知道我可能会做这样的事情:
var i = 0;
for (var obj in myArray) {
alert(i)
i++
}
Or even the good old:
或者甚至是好老:
for (var i = 0; i < myArray.length; i++) {
var obj = myArray[i]
alert(i)
}
But I would rather use the simpler for-in
loop. I think they look better and make more sense.
但我宁愿使用更简单的for-in
循环。我认为它们看起来更好,更有意义。
Is there a simpler or more elegant way?
有没有更简单或更优雅的方法?
In Python it's easy:
在 Python 中很容易:
for i, obj in enumerate(myArray):
print i
回答by Ry-
for…in
iterates over property names, not values, and does so in an unspecified order(yes, even after ES6). You shouldn't use it to iterate over arrays. For them, there's ES5's forEach
method that passes both the value and the index to the function you give it:
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
Or ES6's Array.prototype.entries
, which now has support across current browser versions:
或者 ES6 的Array.prototype.entries
,它现在支持跨当前浏览器版本:
for (const [i, value] of myArray.entries()) {
console.log('%d: %s', i, value);
}
For iterables in general (where you would use a for…of
loop rather than a for…in
), there's nothing built-in, however:
对于一般的可迭代对象(您将使用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);
}
If you actually did mean for…in
– enumerating properties – you would need an additional counter. Object.keys(obj).forEach
could work, but it only includes ownproperties; for…in
includes enumerable properties anywhere on the prototype chain.
如果您确实是指for…in
- 枚举属性 - 您将需要一个额外的计数器。Object.keys(obj).forEach
可以工作,但它只包含自己的属性;for…in
包括原型链上任何地方的可枚举属性。
回答by rushUp
In ES6, it is good to use for - of loop. You can get index in for of like this
在 ES6 中,最好使用 for - of 循环。你可以像这样获得索引
for (let [index, val] of array.entries()) {
// your code goes here
}
Note that Array.entries()
returns an iterator, which is what allows it to work in the for-of loop; don't confuse this with Object.entries(), which returns an arrayof key-value pairs.
请注意,Array.entries()
返回一个迭代器,它允许它在 for-of 循环中工作;不要将此与Object.entries()混淆,后者返回键值对数组。
回答by Sanjay Shr
How about this
这个怎么样
let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))
Where array.forEach
this method has an index
parameter which is the index of the current element being processed in the array.
其中array.forEach
,该方法具有一index
参数,该参数是阵列中当前正在处理的元素的索引。
回答by iwasborntobleed
Solution for small array collections:
小数组集合的解决方案:
for (var obj in arr) {
var i = Object.keys(arr).indexOf(obj);
}
arr- ARRAY, obj- KEY of current element, i- COUNTER/INDEX
arr- ARRAY, obj- 当前元素的 KEY, i- COUNTER/INDEX
Notice:Method keys()is not available for IE version <9, you should use Polyfillcode. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
注意:方法keys()不适用于 IE 版本 <9,您应该使用Polyfill代码。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
回答by Bergi
For-in-loops iterate over properties of an Object. Don't use them for Arrays, even if they sometimes work.
For-in 循环迭代对象的属性。不要将它们用于数组,即使它们有时有效。
Object properties then have no index, they are all equal and not required to be run through in a determined order. If you want to count properties, you will have to set up the extra counter (as you did in your first example).
对象属性则没有索引,它们都是相等的,不需要按确定的顺序运行。如果要计算属性,则必须设置额外的计数器(就像在第一个示例中所做的那样)。
loop over an Array:
循环数组:
var a = [];
for (var i=0; i<a.length; i++) {
i // is the index
a[i] // is the item
}
loop over an Object:
循环对象:
var o = {};
for (var prop in o) {
prop // is the property name
o[prop] // is the property value - the item
}
回答by Robert Messerle
As others have said, you shouldn't be using for..in to iterate over an array.
正如其他人所说,您不应该使用 for..in 来迭代数组。
for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }
If you want cleaner syntax, you could use forEach:
如果你想要更简洁的语法,你可以使用 forEach:
myArray.forEach( function ( val, i ) { ... } );
If you want to use this method, make sure that you include the ES5 shim to add support for older browsers.
如果要使用此方法,请确保包含 ES5 shim 以添加对旧浏览器的支持。
回答by Renish Gotecha
Answer Given by rushUp Is correct but this will be more convenient
rushUp 给出的答案是正确的,但这会更方便
for (let [index, val] of array.entries() || []) {
// your code goes here
}
回答by sospedra
On top of the very good answers everyone posted I want to add that the most performant solution is the ES6 entries
. It seems contraintuitive for many devs here, so I created this perf benchamrk.
除了每个人都发布的非常好的答案之外,我想补充一点,性能最高的解决方案是 ES6 entries
。对于这里的许多开发人员来说,这似乎是有约束的,所以我创建了这个 perf benchamrk。
It's ~6 times faster. Mainly because doesn't need to: a) access the array more than once and, b) cast the index.
它快了约 6 倍。主要是因为不需要:a) 多次访问数组,b) 转换索引。
回答by Rivenfall
Here's a function eachWithIndex
that works with anything iterable.
这是一个eachWithIndex
适用于任何可迭代对象的函数。
You could also write a similar function eachWithKey
that works with objets using for...in
.
您还可以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)
The good thing with generators is that they are lazy and can take another generator's result as an argument.
生成器的好处是它们很懒惰,可以将另一个生成器的结果作为参数。
回答by akurtser
That's my version of a composite iterator that yields an index and any passed generator function's value with an example of (slow) prime search:
这是我的复合迭代器版本,它产生一个索引和任何传递的生成器函数的值,并以(慢)素数搜索为例:
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
}