W3docs

Herança de Classes em JavaScript

Aprenda herança de classes em JavaScript com extends e super: cadeia de protótipos, substituição de métodos e propriedades, chamada de código pai, extensão de built-ins e herança de métodos estáticos.

Introdução à Herança de Classes em JavaScript

A herança de classes é um conceito fundamental da programação orientada a objetos que permite que uma classe herde propriedades e métodos de outra classe. Em JavaScript, a herança de classes é implementada usando a palavra-chave extends, fornecendo uma forma de criar uma classe derivada que herda de uma classe base.

Para mais informações sobre a sintaxe básica, consulte JavaScript: Classes e Sintaxe Básica.

Este capítulo aborda como criar classes derivadas, substituir métodos e propriedades, chamar o pai com super, estender classes nativas como Array, e herdar métodos estáticos — além da cadeia de protótipos que faz tudo isso funcionar internamente.

Como Funciona a Herança: A Cadeia de Protótipos

A palavra-chave class é açúcar sintático sobre a herança prototípica do JavaScript. Quando você escreve class Circle extends Shape, o motor configura dois vínculos:

  • Circle.prototype.__proto__ === Shape.prototype — para que os métodos de instância sejam resolvidos pela cadeia.
  • Circle.__proto__ === Shape — para que os métodos estáticos também sejam herdados.

Quando você lê uma propriedade ou chama um método em um objeto, o motor verifica primeiro o próprio objeto. Se não for encontrado lá, ele percorre a cadeia de protótipos — para Circle.prototype, depois Shape.prototype, depois Object.prototype, e então null — parando no primeiro resultado encontrado. É exatamente por isso que uma instância de Circle pode chamar um método definido em Shape.

javascript— editable

Object.getPrototypeOf(obj) retorna o próximo elo da cadeia (a forma padrão e preferida de inspecioná-la). O acessor legado obj.__proto__ aponta para o mesmo objeto. Compreender essa cadeia explica tudo o que se segue: a substituição funciona porque um protótipo mais próximo sobrepõe um mais distante, e super funciona porque pula explicitamente para o protótipo do pai.

Criando uma Classe Derivada

Para criar uma classe que herda de outra, usamos a palavra-chave extends:

javascript— editable

Neste exemplo, Circle estende Shape, o que significa que herda as propriedades e métodos de Shape e, ao mesmo tempo, fornece métodos próprios. Note que Circle não define seu próprio construtor. Em JavaScript, classes derivadas sem um construtor explícito chamam automaticamente super() com os mesmos argumentos passados ao construtor da classe derivada.

Substituindo Métodos

Classes derivadas podem substituir métodos de suas classes base para fornecer comportamento específico à subclasse.

javascript— editable

Aqui, Circle substitui o método print para refletir seu tipo específico.

Chamando Métodos do Pai com super

Você também pode chamar o método de uma classe pai a partir da classe derivada usando super.methodName(). Isso é útil quando você deseja estender o comportamento do pai em vez de substituí-lo completamente.

javascript— editable

Aqui, super.print() executa a lógica do pai antes de adicionar a saída específica da subclasse.

Uma Substituição Realista: Calculando Área

A substituição se destaca quando cada subclasse precisa de um comportamento genuinamente diferente. Aqui, uma Shape base define a interface compartilhada, e cada subclasse substitui area() com seu próprio cálculo. Chamar area() em um Circle resolve para Circle.prototype.area, que sobrepõe a versão base.

javascript— editable

Observe que describe() é definido apenas em Shape, mas chama this.area() e obtém a implementação da subclasse. Isso é a cadeia de protótipos em ação: this sempre se refere à instância real, então a busca pelo método começa em Circle ou Rectangle.

Substituindo Propriedades e Lendo super.prop

super não se limita a métodos — você pode ler uma propriedade definida no protótipo do pai com super.prop, o que é útil quando uma subclasse quer se basear no getter do pai em vez de substituí-lo.

javascript— editable

Acessando o Construtor do Pai: a Palavra-chave super

Quando uma classe estende outra, a função construtora da classe derivada precisa chamar o construtor do pai usando super() antes de poder usar this. Veja como super é usado em construtores para garantir que a classe pai seja inicializada:

javascript— editable

Por que super() Deve Ser Executado Antes de this

Em uma classe derivada, o objeto instância não é criado até que super() seja executado — essa é a responsabilidade do construtor pai. Até então, this está em um estado não inicializado, portanto tocá-lo (lendo, atribuindo ou até retornando o objeto implicitamente) lança um ReferenceError. Esta é uma regra da linguagem, não uma preferência de estilo.

javascript— editable

Uma regra relacionada: se uma classe derivada define um construtor, ela deve chamar super() em algum lugar antes de finalizar, ou o mesmo ReferenceError é lançado. (Uma classe derivada sem construtor explícito não tem problema — o JavaScript insere constructor(...args) { super(...args); } automaticamente.) Uma vez que super() retorna, this está totalmente inicializado e pronto para uso.

Herdando Métodos Estáticos

Membros estáticos pertencem à própria classe, não a instâncias. Como extends também vincula Circle.__proto__ a Shape, classes derivadas herdam métodos estáticos e podem chamá-los diretamente. Para mais informações sobre como declará-los, consulte Propriedades e Métodos Estáticos em JavaScript.

javascript— editable

Dentro de um método estático, this refere-se à classe na qual foi invocado, então Shape.create chamado como Circle.create constrói um Circle.

Herança em Múltiplos Níveis

As cadeias podem ter mais de dois níveis de profundidade. A busca por métodos simplesmente percorre mais acima na cadeia de protótipos, e super sempre se refere ao protótipo um nível acima da classe onde o método está definido.

javascript— editable

Estendendo Classes Nativas

Você pode estender classes nativas como Array, Error ou Map para criar versões especializadas que mantêm todo o comportamento nativo enquanto adicionam o seu.

javascript— editable

A armadilha do Symbol.species. Métodos como map, filter e slice retornam uma nova coleção. Por padrão, eles retornam uma instância da sua subclasse (MyArray), não um Array simples — o que geralmente está bem, mas pode surpreender código que espera um Array de verdade. Você pode reverter para arrays simples substituindo o getter estático Symbol.species.

javascript— editable

Para combinar comportamentos de múltiplas fontes (JavaScript não possui herança múltipla), consulte Mixins em JavaScript.

Resumo

Principais pontos:

  • Use extends para derivar uma classe; isso vincula tanto a cadeia de protótipos (métodos de instância) quanto a própria classe (métodos estáticos) ao pai.
  • A busca por métodos e propriedades percorre a cadeia de protótipos, parando no primeiro resultado — é por isso que uma definição mais próxima substitui uma mais distante. Inspecione a cadeia com Object.getPrototypeOf().
  • Em um construtor derivado, chame super() antes de this. Até que super() seja executado, a instância não está inicializada e qualquer uso de this lança um ReferenceError.
  • Acesse o comportamento do pai explicitamente com super.method() ou super.prop, mesmo quando você o substituiu.
  • Você pode estender classes nativas como Array — apenas fique atento ao comportamento do Symbol.species quando métodos retornam novas coleções.

Próximos passos:

Prática

Prática
Em herança de classes JavaScript, quais afirmações são verdadeiras?
Em herança de classes JavaScript, quais afirmações são verdadeiras?
Was this page helpful?