Home  >  Q&A  >  body text

Extend keys() and other generator methods of Map class in javascript

I needed to use an object as the key for my map, so I extended the map class that stringified the passed object as follows

class CoordMapper extends Map {
    set = (k: ISquareCoordinate, v: Array<ISquareCoordinate>) => {
        const stringifiedKey = JSON.stringify(k)
        return super.set(stringifiedKey,v)
    }

    get = (k: ISquareCoordinate) => {
        const stringifiedKey = JSON.stringify(k)
        return super.get(stringifiedKey)
    }
}

As far as I understand keys(), values() and entries() are generator methods, so I can do something similar

* keys() {
   const keysArr = [...super.keys()]
   for (const key of keysArr){
      yield JSON.parse(key)
   }
}

But this causes me to load all the keys I wish to avoid, is there a better way?

edit: While Map does have objects as keys, it only checks objects by reference. for example

let newMap = Map()
const obj1 = {'a': 1, 'b' :2}
newMap.set(obj1, 123)
const copyObj1 = {...obj1}
console.log(newMap.get(obj1)) //returns 123
console.log(newMap.get(copyObj1)) //returns undefined

I also need the second one console.log returns 123

P粉613735289P粉613735289258 days ago434

reply all(2)I'll reply

  • P粉211273535

    P粉2112735352024-02-04 21:25:11

    In case anyone stumbles here in the future, there is a Phase 3 proposal If approved, it will add syntactic sugar for iterators so that you can do things like:

    class CoordMapper extends Map {
      *keys() {
        yield* super.keys().map(key => JSON.parse(key));
      }
    }
    

    Try this (this doesn't work yet):

    console.config({ maximize: true });
    
    class CoordMapper extends Map {
      set(k, v) {
        return super.set(JSON.stringify(k), v)
      }
      get(k) {
        return super.get(JSON.stringify(k));
      }
      *keys() {
        console.log(super.keys())
        yield* super.keys().map(JSON.parse);
      }
    }
    
    const c = new CoordMapper();
    
    c.set({ foo: 'bar' }, 0);
    c.set({ baz: 42 }, 1);
    c.set({ qux: { lorem: 'ipsum' } }, [null, undefined]);
    
    for (const key of c.keys()) {
      console.log(key);
    }
    sssccc

    reply
    0
  • P粉311089279

    P粉3110892792024-02-04 00:20:53

    Instead of collecting all parent values ​​into an array, iterate over them directly:

    * keys() {
       const parentKeyIterator = super.keys();
       for (const key of parentKeyIterator){
          yield JSON.parse(key)
       }
    }

    This way, the laziness of the iterator is preserved: every time next() is called on the extended iterator, it will call next( on the parentKeyIterator ) once, then reaches the yield statement, then pauses.

    reply
    0
  • Cancelreply