简体   繁体   中英

javascript - get index in Map.prototype.forEach()

Map.prototype.forEach takes callback with two params: value and key. Is it possible to get the index of each entry, similar to Array.prototype.forEach((value, index) => {})

Map.prototype.forEach takes callback with two params: value and key.

No, it's invoked with three arguments , just like Array#forEach . The third is the map.

Is it possible to get the index of each entry, similar to Array.prototype.forEach(functcion(value, index) => {})

(Fairly sure the functcion part of that wasn't meant to be there.)

That's what key is. There is no separate "index."

Map 's iteration order is defined for various iteration operations, but there's no direct iteration construct that gives you the index (as opposed to key ) of an entry in that order. The order is original key insertion order , so for instance:

const m = new Map();
m.set("x", 1);
m.set("q", 2);
m.set("z"), 3);
m.set("x", "one");

If we loop through that map, we'll see the keys in the order the key was first added, so "x" , "q" , "z" . Note that changing the value of the entry with the ke "x" didn't move it to the end.

Map#forEach (and for-of and anything else using the map's iterator) follows the iteration order, so if you're thinking of the index in terms of that order, you could track the index yourself:

 const m = new Map(); m.set("one", "uno"); m.set("two", "due"); m.set("three", "tre"); let index = 0; m.forEach((value, key) => { console.log(index++, key, value); }); 

Alternately, you can get an array of the map entries (as [key, value] arrays):

let entries = Array.from(m.entries());

...and use the indexes of that array:

I'm just not sure what it buys you. :-)

I don't think so. Map object is a key/value map. To me at least the idea of an index doesn't make much sense, given that the order of the key/value pairs should not be guaranteed in a Map. If you are just curious how many pairs you have iterated on so far, you could just keep a counter that you mutate on each call, something like:

mapObj.forEach(() => {
    let i=0;
    return (key, value) => {
        // whatever you are doing with each key/value
        i += 1;
    }
});

It is not as elegant as an index as parameter, but would at least meet your needs.

The problem is defining what an index is. The spec defines a [[MapNextIndex]] internal slot of iterators, which stores the index of the [[MapData]] list which contains the next entry.

However, there is no way to access these indices. Even more, implementations are not required to internally behave like described by the spec, so they may not have these indices at all.

The data structures used in this Map objects specification is only intended to describe the required observable semantics of Map objects. It is not intended to be a viable implementation model.

What you can do is use an index which says how many times you have to call next() on a new iterator in order to get that entry. These kind of indexes are not absolute, and may become obsolete if you alter the map. Just initialize a counter to 0 , and increase it at each iteration.

{
  let i = 0;
  for(var [key,value] of map) {
    // Do something
    ++i;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM