Rozšíření vestavěných tříd

Vestavěné třídy jako Array, Map a další jsou také rozšiřitelné.

Například zde PowerArray dědí z nativního Array :

// add one more method to it (can do more)
class PowerArray extends Array {
 isEmpty() {
 return this.length === 0;
 }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

let filteredArr = arr.filter(item => item >= 10);
alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false

Všimněte si velmi zajímavé věci. Vestavěné metody jako filter , map a další – vrátí nové objekty přesně zděděného typu PowerArray . Jejich interní implementace používá objekt constructor majetek za to.

Ve výše uvedeném příkladu

arr.constructor === PowerArray

Když arr.filter() zavolá, interně vytvoří nové pole výsledků pomocí přesně arr.constructor , nikoli základní Array . To je vlastně velmi skvělé, protože můžeme nadále používat PowerArray metody dále na výsledek.

Navíc můžeme toto chování přizpůsobit.

Můžeme přidat speciální statický getr Symbol.species do třídy. Pokud existuje, měl by vrátit konstruktor, který JavaScript použije interně k vytvoření nových entit v map , filter a tak dále.

Pokud bychom chtěli vestavěné metody jako map nebo filter abychom vrátili běžná pole, můžeme vrátit Array v Symbol.species , jako zde:

class PowerArray extends Array {
 isEmpty() {
 return this.length === 0;
 }

 // built-in methods will use this as the constructor
 static get [Symbol.species]() {
 return Array;
 }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

// filter creates new array using arr.constructor[Symbol.species] as constructor
let filteredArr = arr.filter(item => item >= 10);

// filteredArr is not PowerArray, but Array
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function

Jak můžete vidět, nyní .filter vrátí Array . Rozšířená funkcionalita tedy není předávána dále.

Podobně fungují i ​​další kolekce

Jiné sbírky, například Map a Set , pracovat stejně. Používají také Symbol.species .

Žádné statické dědění ve vestavěných modulech

Vestavěné objekty mají své vlastní statické metody, například Object.keys , Array.isArray atd.

Jak již víme, nativní třídy se navzájem rozšiřují. Například Array rozšiřuje Object .

Normálně, když jedna třída rozšiřuje druhou, dědí se statické i nestatické metody. To bylo důkladně vysvětleno v článku Statické vlastnosti a metody.

Ale vestavěné třídy jsou výjimkou. Nedědí od sebe statiku.

Například obě Array a Date dědit z Object , takže jejich instance mají metody z Object.prototype . Ale Array.[[Prototype]] neodkazuje na Object , takže zde není například Array.keys() (nebo Date.keys() ) statická metoda.

Zde je struktura obrázku pro Date a Object :

Jak vidíte, mezi Date není žádné spojení a Object . Jsou nezávislé, pouze Date.prototype dědí z Object.prototype .

To je důležitý rozdíl v dědičnosti mezi vestavěnými objekty ve srovnání s tím, co získáme pomocí extends .