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

2020/10/02 01:01 · javascript ·  · 0评论

警告:

问题仍然适用于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

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循环而不是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在原型链的任何位置都包含可枚举的属性。

在ES6中,最好将-用于循环。您可以像这样获得索引

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

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

这个怎么样

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

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

小数组集合的解决方案:

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

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

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

循环中遍历对象的属性。即使它们有时起作用,也不要将它们用于数组。

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

遍历数组:

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
}

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

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

如果您希望语法更简洁,则可以使用forEach:

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

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

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

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

要在数组上使用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
}

这是一个eachWithIndex可以处理任何迭代的函数

您还可以使用编写eachWithKey与objets一起使用的类似函数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)

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

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

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 entries对于这里的许多开发人员来说,这似乎是矛盾的,所以我创建了这个perf Benchamrk

在此处输入图片说明

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

本文地址:http://javascript.askforanswer.com/zaijavascriptzhongshiyongforofyufahuoquxunhuanjishuqi-suoyin.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!