使用JavaScript中的语法获取循环计数器/索引

hob*_*es3 252 javascript foreach counter for-loop

警告:

问题仍然适用于for…of循环.>不要使用for…in迭代数组,用它来迭代对象的属性.那说,这个


我知道for…inJavaScript 中的基本语法如下所示:

for (var obj in myArray) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

我知道我可能做的事情如下:

var i = 0;
for (var obj in myArray) {
    alert(i)
    i++
}
Run Code Online (Sandbox Code Playgroud)

甚至是好老:

for (var i = 0; i < myArray.length; i++) {
    var obj = myArray[i]
    alert(i)
}
Run Code Online (Sandbox Code Playgroud)

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

有更简单或更优雅的方式吗?


在Python中很简单:

for i, obj in enumerate(myArray):
    print i
Run Code Online (Sandbox Code Playgroud)

Ry-*_*Ry- 433

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
Run Code Online (Sandbox Code Playgroud)

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

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

对于一般的iterables(你将使用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);
}
Run Code Online (Sandbox Code Playgroud)

演示

如果你真的意味着for…in- 枚举属性 - 你需要一个额外的计数器.Object.keys(obj).forEach可以工作,但它只包括自己的属性; for…in包括原型链上任何位置的可枚举属性.

  • @quantumpotato:`let` 是具有块作用域的 `var`。`const` 是不变的。 (3认同)
  • 这是一个详细的答案,谢谢。真正澄清了所有讨论的事情 (3认同)
  • 哦好的。我很困惑。我认为 JavaScript 的 for-in 与 Python 的相同。感谢您的澄清。 (2认同)
  • 愚蠢的问题,但 %d 和 %s 实际上代表什么,或者它们可以是我想要的任何字母吗? (2认同)
  • @klewis:“%d”格式化整数,“%s”格式化字符串。它们基于 [printf](https://en.wikipedia.org/wiki/Printf_format_string)。https://console.spec.whatwg.org/#formatter 上的规范正在进行中。 (2认同)
  • `forEach` 的缺点是内部的 `await` 的作用域是函数参数,而不是外部作用域。因此,如果您想在循环内等待,您可能需要使用`.entries()`。 (2认同)

小智 132

在ES6中,最好使用for-of循环.您可以获得这样的索引

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

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

  • 这是一个比被接受的答案更好的答案! (8认同)
  • 我认为这种解决方案比forEeach更好。它使用名义上的for ... of循环语法,您不必使用单独的函数。换句话说,它在语法上更好。OP似乎想要这个。 (3认同)
  • Joshua应该做到这一点-该对象是一个迭代器,一个具有`next()`方法的对象,该对象将在每次调用时返回数组中的后续条目。里面没有(可见)数据。您可以通过调用`next()`在底层对象中获取数据,for-of在幕后进行。cc @tonyg (2认同)
  • 此外,这允许“await”按顺序工作,而“forEach”则不能。 (2认同)
  • 请注意,这只适用于“Array”。`for...of` 适用于任何 `Iterable`。您可能必须使用“for (const [index, value] of [...array].entries())”转换为“Array”。可迭代对象包括“HTMLCollection”、“NodeList”和其他 DOM 类。 (2认同)

San*_*Shr 19

这个怎么样

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

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

  • 选择的答案发布于此版本的6年之前,并且已经包含了相同的内容... (3认同)
  • Foreach 不利于优化,因为“break”不可用。 (2认同)

iwa*_*eed 17

小数组集合的解决方案:

for (var obj in arr) {
    var i = Object.keys(arr).indexOf(obj);
}
Run Code Online (Sandbox Code Playgroud)

arr - ARRAY, obj - 当前元素的关键字, i - COUNTER/INDEX

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

  • 我建议:使用计数器代替,在循环中增加它. (7认同)
  • 物体越大,速度就越慢。这无法扩展。 (3认同)
  • 添加到mayankcpdixit,请使用计数器,因为indexOf可能会对性能产生负面影响. (2认同)
  • 这是一种毫无意义的缓慢和复杂,因为`var i = 0;`和`i ++;`更短更高效.此外,它不适用于非属性的可枚举属性. (2认同)

Ber*_*rgi 12

For-in-loops迭代Object的属性.不要将它们用于数组,即使它们有时也可以工作.

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

循环数组:

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

循环对象:

var o = {};
for (var prop in o) {
    prop // is the property name
    o[prop] // is the property value - the item
}
Run Code Online (Sandbox Code Playgroud)

  • @FelixSanz:浪费资源?没门.这是一个几乎不需要的过早的微优化,并且`var i = 0; I <则为a.length; i ++)`是标准的循环模式,无论如何都被每个体面的javascript引擎优化. (13认同)
  • KISS适用于所有地方.[过早优化](https://en.wikipedia.org/wiki/Premature_optimisation)是一种反实践. (3认同)
  • 永远不要做`(var i = 0; i <a.length; i ++)`浪费资源.使用`(var i = 0,var len = a.length; i <len; i ++)` (2认同)
  • @FelixSanz:是的,`var i = 0; i &lt;长度; i ++是最好的做法。 (2认同)

Rob*_*rle 5

正如其他人所说,你不应该使用for..in迭代数组.

for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }
Run Code Online (Sandbox Code Playgroud)

如果您想要更清晰的语法,可以使用forEach:

myArray.forEach( function ( val, i ) { ... } );
Run Code Online (Sandbox Code Playgroud)

如果要使用此方法,请确保包含ES5填充程序以添加对旧版浏览器的支持.


Ren*_*cha 5

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

for (let [index, val] of array.entries() || []) {
   // your code goes here    
}
Run Code Online (Sandbox Code Playgroud)

  • `|| []` 是不必要的,永远不会被使用;`array.entries()` 始终为真。 (3认同)