在 JavaScript 中使用 for...of 语法获取循环计数器/索引

IT技术 javascript for-loop foreach counter
2021-02-02 04:23:43

警告:

问题仍然适用于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
6个回答

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包括原型链上任何地方的可枚举属性。

@quantumpotato:lets 是var具有块作用域的 s。consts 不变。
2021-03-15 04:23:43
@klewis:%d格式化整数并%s格式化字符串。它们基于printfconsole.spec.whatwg.org/#formatter正在制定规范
2021-03-22 04:23:43
哦好的。我很困惑。我认为 JavaScript 的 for-in 与 Python 的相同。感谢您的澄清。
2021-03-30 04:23:43
这是一个详细的答案,谢谢。真正澄清了所有讨论的事情
2021-03-30 04:23:43
愚蠢的问题,但 %d 和 %s 实际上代表什么,或者它们可以是我希望它们是的任何字母?
2021-04-11 04:23:43

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

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

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

它应该这样做,约书亚 - 该对象是一个迭代器,一个具有next()方法的对象,该方法将在每次调用时返回数组中的后续条目。其中没有(可见的)数据;您可以通过调用 获取底层对象中的数据next(),这在幕后进行。抄送@tonyg
2021-03-14 04:23:43
entries()正在返回一个空对象:{}知道为什么会这样吗?Myarray是一个对象数组。
2021-03-18 04:23:43
这是一个比公认的更好的答案!
2021-04-04 04:23:43
我认为这个解决方案比 forEach one 更好......它使用普通的 for...of 循环语法,并且您不必使用单独的函数。换句话说,它在语法上更好。OP 似乎想要这个。
2021-04-09 04:23:43
这也允许await按顺序工作,而forEach不能。
2021-04-11 04:23:43

这个怎么样

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

其中array.forEach,该方法具有一index参数,该参数是阵列中当前正在处理的元素的索引。

选择的答案是在这个答案之前 6 年发布的,并且已经包含相同的内容......
2021-03-24 04:23:43
Foreach 不利于优化,因为break它不可用。
2021-04-04 04:23:43

小数组集合的解决方案:

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

arr - ARRAY, obj - 当前元素的键, i - 计数器/索引

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

这是一种无谓的缓慢和复杂的,因为var i = 0;i++;更短,更高效。此外,它不适用于不是自己的属性的可枚举属性。
2021-03-14 04:23:43
添加到 mayankcpdixit 中,请改用计数器,因为 indexOf 可能会对性能产生负面影响。
2021-03-26 04:23:43
@trusktr:如果需要的话……你仍然不应该使用它。更改集合时只需更改计数器即可。如果它不必就位,请改为进行很好的功能转换。
2021-04-08 04:23:43
我建议:改用计数器,在循环中递增它。
2021-04-09 04:23:43
对象越大,这将变得越慢。这没有规模。
2021-04-12 04:23:43

For-in 循环迭代对象的属性。不要将它们用于数组,即使它们有时有效。

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

循环数组:

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
}
@FelixSanz:浪费资源?没门。这是一个过早的微优化,几乎从来没有必要,并且var i=0; i<a.length; i++)是标准循环模式,无论如何都被每个像样的 javascript 引擎优化。
2021-03-25 04:23:43
@FelixSanz:是的,这var i=0; i<a.length; i++是最好的做法。
2021-03-27 04:23:43
KISS 适用于任何地方。过早的优化是一种反实践。
2021-04-02 04:23:43
永远不要这样做(var i=0; i<a.length; i++)浪费资源。利用(var i=0, var len = a.length; i<len; i++)
2021-04-09 04:23:43
如果你在真正需要的地方编写循环,你要么做错了,要么你有比“最佳实践”更好的理由来证明它的必要性。是的,这是一种标准做法,但不适用于通用性能优化,而仅适用于微优化。
2021-04-09 04:23:43