> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/c-functions/c3-classes/07-species-pattern.md).

# 07. Species Pattern

Sometimes a method creates new instances of its class. If you create a subclass – should the method return an instance of its class or an instance of the subclass? A few built-in ES6 methods let you configure how they create instances via the so-called *species pattern*.

The standard species pattern is used by `Promise.prototype.then()`, the `filter()` method of Typed Arrays and other operations. It works as follows:

* If `this.constructor[Symbol.species]` exists, use it as a constructor for the new instance.
* Otherwise, use a default constructor (e.g. `Array` for `Arrays`).

Implemented in JavaScript, the pattern would look like this:

```javascript
function SpeciesConstructor(O, defaultConstructor) {
  const C = O.constructor;
  if (C === undefined) {
    return defaultConstructor;
  }
  if (!isObject(C)) {
    throw new TypeError();
  }
  const S = C[Symbol.species];
  if (S === undefined || S === null) {
    return defaultConstructor;
  }
  if (!isConstructor(S)) {
    throw new TypeError();
  }
  return S;
}
```

## `Symbol.species`

This is the default getter for the property `[Symbol.species]`:

```javascript
static get [Symbol.species]() {
    return this;
}
```

You can override the default species via a static getter (line A):

```javascript
class MyArray1 extends Array {
  static get [Symbol.species]() {
    // (A)
    return Array;
  }
}
```

As a result, `map()` returns an instance of `Array`:

```javascript
const result1 = new MyArray1().map(x => x);
console.log(result1 instanceof Array); // true
```

If you don’t override the default species, `map()` returns an instance of the subclass:

```javascript
class MyArray2 extends Array {}

const result2 = new MyArray2().map(x => x);
console.log(result2 instanceof MyArray2); // true
```
