Classes integradas como Array, Map e outras também são extensíveis.
Por exemplo, aqui PowerArray
herda do Array
nativo:
// adiciona mais um método (pode fazer mais) classe PowerArray estende Array { estáVazio() { retornar este.comprimento === 0; } } deixe arr = novo PowerArray(1, 2, 5, 10, 50); alerta(arr.isEmpty()); // falso deixe filteredArr = arr.filter(item => item >= 10); alerta(Arrfiltrado); // 10, 50 alerta(filteredArr.isEmpty()); // falso
Observe uma coisa muito interessante. Métodos integrados como filter
, map
e outros – retornam novos objetos exatamente do tipo herdado PowerArray
. Sua implementação interna usa a propriedade constructor
do objeto para isso.
No exemplo acima,
arr.constructor === PowerArray
Quando arr.filter()
é chamado, ele cria internamente o novo array de resultados usando exatamente arr.constructor
, não o básico Array
. Na verdade, isso é muito legal, porque podemos continuar usando os métodos PowerArray
mais adiante no resultado.
Ainda mais, podemos personalizar esse comportamento.
Podemos adicionar um getter estático especial Symbol.species
à classe. Caso exista, deverá retornar o construtor que o JavaScript usará internamente para criar novas entidades em map
, filter
e assim por diante.
Se quisermos que métodos integrados como map
ou filter
retornem arrays regulares, podemos retornar Array
em Symbol.species
, como aqui:
classe PowerArray estende Array { estáVazio() { retornar este.comprimento === 0; } // métodos internos usarão isso como construtor obtenção estática [Symbol.species]() { retornar matriz; } } deixe arr = novo PowerArray(1, 2, 5, 10, 50); alerta(arr.isEmpty()); // falso // filtro cria um novo array usando arr.constructor[Symbol.species] como construtor deixe filteredArr = arr.filter(item => item >= 10); // filteredArr não é PowerArray, mas Array alerta(filteredArr.isEmpty()); // Erro: filteredArr.isEmpty não é uma função
Como você pode ver, agora .filter
retorna Array
. Portanto, a funcionalidade estendida não é mais avançada.
Outras coleções funcionam de forma semelhante
Outras coleções, como Map
e Set
, funcionam de forma semelhante. Eles também usam Symbol.species
.
Objetos integrados têm seus próprios métodos estáticos, por exemplo Object.keys
, Array.isArray
etc.
Como já sabemos, as classes nativas se estendem. Por exemplo, Array
estende Object
.
Normalmente, quando uma classe estende outra, métodos estáticos e não estáticos são herdados. Isso foi explicado detalhadamente no artigo Propriedades e métodos estáticos.
Mas as classes integradas são uma exceção. Eles não herdam a estática um do outro.
Por exemplo, tanto Array
quanto Date
herdam de Object
, portanto suas instâncias possuem métodos de Object.prototype
. Mas Array.[[Prototype]]
não faz referência Object
, então não há, por exemplo, método estático Array.keys()
(ou Date.keys()
).
Aqui está a estrutura da imagem para Date
e Object
:
Como você pode ver, não há link entre Date
e Object
. Eles são independentes, apenas Date.prototype
herda de Object.prototype
.
Essa é uma diferença importante de herança entre objetos integrados em comparação com o que obtemos com extends
.