1

let collection = [{
    name: 'music',
    views: 20
  },
  {
    name: 'abc',
    views: 32
  },
  {

    name: 'bob',
    views: 20
  }
]

for (const [k, v] of collection) {
  console.log(k, v)
}

console.log(Array.isArray(collection))

Error: .for is not iterable

Array.isArray(collection) returns true

How can an array not be iterable?

Do I really need to resort to this to "get" the index of each item?

for (let i = 0; i < collection.length; i++){
    console.log(i, collection[i])
        
}

nvm ...it works fine with forEach

collection.forEach((k, v) => {
    console.log(k,v)
})

What's going with for...of here?

Note: I can't use for...in b/c i need the order to be guaranteed

Barmar
  • 741,623
  • 53
  • 500
  • 612
ThomasRones
  • 657
  • 8
  • 29
  • 5
    the elements of `collection` aren't arrays, so you can't destructure them with `[k, v]`. – Barmar May 18 '23 at 20:42
  • 1
    You want `for (const {name: k, views: v} of collection)` – Barmar May 18 '23 at 20:44
  • @Barmar That's actually not what I want. I want k to be 0,1,2 and v to be each object – ThomasRones May 18 '23 at 20:47
  • 2
    @ThomasRones Then you need `for (const [index, value] of collection.entries())` – Bergi May 18 '23 at 20:49
  • Why do you think `for...in` doesn't guarantee order? – Barmar May 18 '23 at 20:51
  • @Barmar it might work here, but there's various other reasons [not to use `for…in` enumerations on arrays](https://stackoverflow.com/q/500504/1048572). – Bergi May 18 '23 at 20:53
  • 1
    @Bergi Thanks, I didn't realize the order wasn't guaranteed. Although I suspect that it only fails in IE < 8 as mentioned in the other question. ES6 has added ordering property ordering requirements, which I expect to carry over to array iteration. – Barmar May 18 '23 at 20:56

1 Answers1

6

for..of iterates only values, not keys and values.
Use Array::entries() to iterate both array indices and values.
On the other hand if you need only properties in your array's items you can use object destructuring:

let collection = [
    {
    name: 'music',
    views: 20
    },
    {
    name: 'abc',
    views: 32
    },
    {

    name: 'bob',
    views: 20
    }   
]

// probably what you wanted
for (const [k, v] of collection.entries()){
    console.log(k, v)
}

// if you need items' properties
for (const {name, views} of collection){
    console.log(name, views)
}

UPDATE
Note that using an iterator like Array::entries() is the slowest way to iterate a big array (a handmade generator function gives the exact same result). In my benchmark in Chrome with a 10000000 items array it slower 1.5-2x times that Array::forEach() and for..of (they are the same thing actually in implementation), and min 6x slower than the old good

for(let i = 0; i < arr.length; i++)

which is still the fastest way to iterate over an array.

Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17