Confusion regarding Map species documentation (and purpose)

Viewed 40

So, reading the docs for Map species:

In a derived collection object (e.g. your custom map MyMap), the MyMap species is the MyMap constructor. However, you might want to overwrite this, in order to return parent Map objects in your derived class methods

Yet, Map doesn't seem to have any methods that actually do anything with this. For example, the only Map method (that I see) that returns a Map is set, yet setting species does nothing to change the result of map.set(...) instanceof .

So what is the purpose of species in regards to the Map object?

My tests:

class MapA extends Map {
    static get [Symbol.species]() {return Map}
}
class MapB extends Map {
    static get [Symbol.species]() {return MapB}
}
let ma = new MapA
let mb = new MapB
console.log("ma instanceof Map",ma instanceof Map)
console.log("ma instanceof MapA",ma instanceof MapA)
console.log("ma.set instanceof Map",ma.set(1,1) instanceof Map)
console.log("ma.set instanceof MapA",ma.set(1,1) instanceof MapA)
console.log("mb instanceof Map",mb instanceof Map)
console.log("mb instanceof MapB",mb instanceof MapB)
console.log("mb.set instanceof Map",mb.set(1,1) instanceof Map)
console.log("mb.set instanceof MapB",mb.set(1,1) instanceof MapB)

My test outputs:

ma instanceof Map true
ma instanceof MapA true
ma.set instanceof Map true
ma.set instanceof MapA true
mb instanceof Map true
mb instanceof MapB true
mb.set instanceof Map true
mb.set instanceof MapB true

My test is showing me that the only Map method I know that returns a Map instance ignores the species and just returns an instance of the class it was called on

1 Answers

The species pattern only relates to creating new instances. set returns the Map you call it on, so it doesn't use [Symbol.species].

Map doesn't currently have any methods that create new Map instances, but I can see at least two reasons [Symbol.species] is defined for it:

  1. Subclasses - A Map subclass may well define a method that returns a new instance, in which case it might use the species pattern even though Map itself doesn't.
  2. Future additions to Map - New methods that create instances may well be added to Map at some stage.

Set also has [Symbol.species], and also doesn't have any methods that create new instances — yet. There is a proposal for new methods that will create instances such as intersection and union and others.

Since the species pattern was added to handle array subclasses well (since arrays have methods like slice and map that create new instances), it made sense to apply it to other container classes that may at some point have methods to create new instances, and for subclasses to use.

Related