• Home

    Escolha seu Plano

    Carreiras Alura

    Evolua com profundidade técnica, direção clara e aplicação prática.

    Jornadas guiadas do básico ao avançado com checkpoints práticos, desenhadas para quem busca profundidade e protagonismo técnico.

    Iniciante

    Comece do zero com uma trilha clara e progressiva.

    Fundamentos práticos para dar os primeiros passos com segurança e construir uma base sólida.

    Intermediário

    Continue sua evolução com cursos que conectam fundamentos, ferramentas e prática profissional. Ganhe autonomia, e avance para projetos mais completos.

    Avançado

    Aprofunde temas técnicos e estratégicos para enfrentar desafios mais complexos. Explore boas práticas, arquitetura, performance com visão profissional.

    Cursos

    Ver mais cursos de Back-end
    • Pensamento computacional: fundamentos da computação e lógica de programação
    • Lógica de programação: mergulhe em programação com JavaScript
    • DDD: fundamentos do design orientado a domínio
    • ASP.NET: autenticação e autorização em APIs e aplicações web
    • Microsserviços: migração de monólitos e modularização

    Cursos

    Ver mais cursos de Dados
    • Python para Dados: primeiros passos
    • Excel: domine o editor de planilhas
    • Engenharia de Dados: Orquestração de Pipelines com Apache Airflow
    • Power BI Desktop: construindo meu primeiro dashboard
    • Governança e Arquitetura de Dados

    Cursos

    Ver mais cursos de Inteligência Artificial
    • IA: Explorando o Potencial da Inteligência Artificial Generativa
    • Engenharia de Prompt: Criando Prompts Eficazes para IA Generativa
    • Claude para Análise de Dados: prompts, integrações e automações
    • Agno: criando agentes e sistemas multiagente
    • Engenharia de software na era da IA: segurança de aplicações com agentes, MCPs e código gerado por IA

    Cursos

    Ver mais cursos de Front-end
    • HTML e CSS: ambiente, estrutura e estilo
    • React: realizando testes avançados com Jest e Testing Library
    • React: integrando TypeScript em projetos
    • JavaScript: aprendendo a programar
    • React: aplicando arquiteturas de Micro frontends

    Cursos

    Ver mais cursos de DevOps
    • Sistema Operacional Linux: fundamentos e administração prática
    • Containers e Docker: empacotamento, isolamento e gestão
    • Redes: dos conceitos iniciais à criação de uma intranet
    • Linux: gerenciando diretórios, arquivos, permissões e processos
    • Cibersegurança: Fundamentos e práticas integradas

    Cursos

    Ver mais cursos de UX & Design
    • UX Research: mapeando a experiência da pessoa usuária
    • UX/UI Design: Entregando produtos digitais com IA
    • UI Design: Prototipação e animações interativas
    • Figma: Conhecendo o programa
    • Product Design: métricas e ciclo de vida do produto

    Cursos

    Ver mais cursos de Gestão & Negócios
    • Canva: Criação de landing pages e e-mail marketing
    • Agilidade: como ela pode ajudar a criar um time de alta performance
    • Google Analytics 4: Extrair insights e configurar eventos
    • Management 3.0: gerencie o ambiente, não as pessoas
    • Automação de processos com n8n: Inteligência de dados para Marketing

    Cursos

    Ver mais cursos de Mobile
    • React Native: Estilização e Layouts com Flexbox e StyleSheet
    • Flutter: Graphql e suporte offline
    • Android com Gemini: Trabalhando com textos e imagens na IA
    • Dart: trabalhando com orientação a objetos
    • React Native: Dominando Listas com FlatList e ScrollView

    Carreiras

    Ver mais carreiras
    • Especialista em IA
    • Engenharia de IA
    • Ai native software engineering
    • Arquitetura de Soluções com IA
    • AI Product Design
    • Engenharia de Machine Learning
    • Desenvolvimento Front-End React
    • Engenharia de Dados
    • Cloud Security
    • Social Media Marketing
    • Engenharia de Agentes de IA

    Cursos

    • Engenharia de Prompt: Prompts Eficazes para IA Generativa
    • Claude Code: Criando sua Primeira Aplicação
    • Python: Crie sua Primeira Aplicação
    • Git e GitHub: Compartilhando e Colaborando
    • N8N: Fluxos de Trabalho Avançados

    Cursos

    • Copilot Studio: Solução Multiagentes
    • Padrões de API HTTP e Modelagem de APIs
    • Python para Análise de Dados com SQL
    • Docker: Criando e Gerenciando Containers
    • Design com IA: Otimizando o Processo Criativo

    Cursos

    • Model Context Protocol (MCP)
    • Spec-Driven Development: Dev Assistido por Agentes
    • Arquitetura de Sistemas Distribuídos com Java
    • Governança de Modelos e Reprodutibilidade
    • Pentest: Vulnerabilidades em Aplicações Web

    Escolha seu Plano

    Skills & Go

    O Skills & Go é para Tech Leads, Product Managers, estrategistas e early adopters que transformam ideias em soluções de alto impacto. Em cursos ao vivo e 100% online, você domina a nova era da IA em tempo real.

    Aulas ao vivo

    Saiba mais
    • Agentic Engineering: orquestre múltiplos agentes com confiabilidade
    • Building AI Products: transforme ideias em produtos reais com IA
    • AI Data Strategy: transforme dados em decisões estratégicas com IA

    Escolha seu Plano

    Eventos Alura

    Nossos eventos são pensados para quem quer estar à frente das mudanças em tecnologia, IA e inovação. Em experiências presenciais, você acompanha tendências e se conecta com especialistas que estão moldando o futuro.

    Próximos eventos

    • Imersão Engenharia de Software: Dev na Era da IA
    • IA Conference
    • Alura Signals
  • Talent Lab
  • IA

    Escolha seu Plano

    Conteúdos gratuitos

    Explore conteúdos gratuitos para aprender tecnologia no seu ritmo. Encontre artigos com conteúdos técnicos para aprender na prática, notícias para acompanhar as principais tendências do mercado e o Alura Labs, com análises e reflexões de especialistas sobre tecnologia, IA e carreira.

    Conteúdos gratuitos

    • Artigos
    • Notícias
    • Alura Labs
  • Para Empresas
Ver planos
Links principais
  • Planos e Promoções
  • Links complementares do menu mobile
  • Talent lab
  • Inteligência Artificial
  • Pós Graduações
  • Para Empresas
  • Sobre a Alura
  • Grupo Alun
  • Entrar
    • Home
    • Carreiras
    • Skills & Go
    • Talent Lab
    • Inteligência Artificial
    • Pós Graduações
    • Artigos
    • Sobre a Alura
    • Grupo Alun
    LoginContato
    • LinkedIn
    • Instagram
    • YouTube
    1. Página inicial
    2. Front-end
    3. Reaproveitando código com JavaScript: herança e protótipos

    Reaproveitando código com JavaScript: herança e protótipos

    8 min8 minutos de leitura

    Alura

    8 min8 minutos de leitura

    Publicado: 25/05/2014

    1. Introdução
    2. 1 - Prototype-chaining Inheritance
    3. 2 - Parasitic Combination Inheritance
    4. 3 - Functional Inheritance
    5. Para saber mais

    Introdução

    Quando estamos desenvolvendo um sistema orientado a objetos, é comum termos uma certa preocupação com repetição de código.

    Imagine que nós implementamos um sistema contendo uma entidade Pessoa (com nome e email), mas surgiu agora a necessidade temos um tipo mais específico de Pessoa: PessoaFisica, que contém todos os comportamentos de Pessoa e, além disso, sabe dizer seu CPF.

    No mundo da orientação a objetos, seria comum utilizarmos herança para não precisar copiar os atributos e métodos da classe Pessoa. Mas e no JavaScript, como poderíamos implementar isso?

    Existem diversos modos de se implementar herança em JavaScript. Nesse post, eu tentarei cobrir as seguintes maneiras:

    • Prototype-chaining Inheritance
    • Parasitic Combination Inheritance
    • Functional Inheritance
    Banner do Guia Tático Alura sobre carreira em tecnologia, destacando o mapa da carreira tech. A imagem convida a explorar diferentes caminhos profissionais, comparar possibilidades e encontrar a próxima fase da carreira na área de tecnologia, com chamada “Explore o mapa”.

    1 - Prototype-chaining Inheritance

    Antes de pensarmos na herança, vamos escrever uma função construtora utilizando o Pseudo-classical pattern para representar a Pessoa :

     var Pessoa = function(nome, email){ this.nome = nome; this.email = email };
    Pessoa.prototype.fala = function(){ console.log("Olá, meu nome é "+this.nome+" e meu email é "+this.email); }; 
    

    Mas note que, deste modo, nada impede que um desenvolvedor instancie uma pessoa com um email inválido:

     var leoInvalido = new Pessoa("Leonardo", "emailinvalido"); 
    

    Por estarmos utilizando uma função construtora, fica fácil resolver esse problema:

     var Pessoa = function(nome, email){ this.nome = nome; if(emailEhValido(email)) this.email = email }; 
    

    Bacana, já temos a nossa Pseudo-classe representando uma Pessoa. Mas, como disse anteriormente, nós precisamos de um outro tipo de pessoa: uma PessoaFisica, que possui CPF e sabe dizê-lo:

     var PessoaFisica = function(nome, email, cpf){ this.nome = nome; this.email = email; this.cpf = cpf; };
    PessoaFisica.prototype.dizCpf = function(){ console.log(this.cpf); }; 
    

    Mas note que, do jeito que implementamos a função construtora PessoaFisica, ela não está verificando se o email foi preenchido corretamente como estávamos fazendo na Pessoa!

    Vamos então reaproveitar a verificação que escrevemos anteriormente. Para isso, basta chamar a função Pessoa utilizando a nossa instância (this) como referência.

    Essa técnica é chamada de Constructor Stealing :

     var PessoaFisica = function(nome, email, cpf){ Pessoa.call(this, nome, email); this.cpf = cpf; };
    PessoaFisica.prototype.dizCpf = function(){ console.log(this.cpf); }; 
    

    Isso fará com que nossa PessoaFisica tenha todos os atributos que uma Pessoa teria!

    Neste outro post, mostrei que os prototypes servem justamente para adicionar métodos a todas as instâncias de determinada função. Note que é exatamente esse o comportamento que falta em nossa classe PessoaFisica! Queremos que ela tenha todos os métodos que uma instância da função Pessoa teria.

    Então, para herdarmos os métodos de Pessoa, basta setarmos o prototype da PessoaFisica para uma instância de Pessoa:

     PessoaFisica.prototype = new Pessoa(); PessoaFisica.prototype.constructor = PessoaFisica; // corrige o ponteiro do construtor 
    

    Obs: Alguns diriam que é uma má pratica instanciar uma Pessoa sem argumentos para atribuir ao prototype de PessoaFisica, e eles estão certos! Deste modo, além de criarmos uma Pessoa inconsistente (com os atributos nome e email vazios), acabamos por instanciar um objeto somente para atribuir ao protótipo da PessoaFisica, consumindo tempo de execução e memória. Na estratégia Parasitic Combination Inheritance veremos um jeito melhor de fazer isso!

    Note que, a partir do momento que você sobrescreveu o prototype de PessoaFisica, você perdeu o método dizCpf!

    Para resolvermos esse problema, basta declararmos o método depois de sobrescrever o prototype:

     PessoaFisica.prototype = new Pessoa(); PessoaFisica.prototype.constructor = PessoaFisica; // corrige o ponteiro do construtor PessoaFisica.prototype.dizCpf = function(){ console.log(cpf); }; 
    

    Agora podemos, ao instanciar uma PessoaFisica, chamar o método fala() que foi declarado na função Pessoa:

     var leonardo = new PessoaFisica("Leonardo", "[email protected]", "meucpf"); leonardo.fala(); // Olá, meu nome é Leonardo e meu email é [email protected] leonardo.dizCpf(); //meucpf 
    

    Perceba que agora, para instanciar uma PessoaFisica, nós chamamos a função Pessoa duas vezes: ao setar o protótipo da função filha e ao instanciar a função filha.

    Esta é a maneira mais comum de se implementar herança em javascript, chamada de Prototype-chaining inheritance.

    Confira o resultado da nossa função PessoaFisica herdando Pessoa:

     var Pessoa = function(nome, email) { this.nome = nome;
    if(emailEhValido(email)) this.email = email; }
    Pessoa.prototype.fala = function(){ console.log("Olá, meu nome é "+this.nome+" e meu email é "+this.email); }
    var PessoaFisica = function(nome, email, cpf){ Pessoa.call(this, nome, email); this.cpf = cpf; };
    PessoaFisica.prototype = new Pessoa(); PessoaFisica.prototype.constructor = PessoaFisica; PessoaFisica.prototype.dizCpf = function(){ console.log(this.cpf); };
    

    Nós conseguimos o resultado esperado, mas há quem diga que nosso código acabou ficando poluído com o uso dos prototypes: ao utilizarmos a Prototype-chaining Inheritance nós obtemos ganho de performance e diminuição da memória utilizada, mas como consequência nós acabamos danificando esteticamente o nosso código, como expliquei aqui.

    2 - Parasitic Combination Inheritance

    Nós já vimos que, ao utilizar a Prototype-chaining Inheritance pura, a cada vez que instanciamos uma PessoaFisica, chamamos duas vezes a função Pessoa. Será que não há um modo mais performático de se implementar herança?

    Existe sim, mas antes de entendermos como ele é implementado, precisamos entender a função Object.create, escrita por Douglas Crockford, que usaremos em nossa implementação.

    Essa é a função, que foi incluída ao ECMAScript 5:

     if (typeof Object.create !== 'function') { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } 
    

    Basicamente o que ela faz é criar uma função construtora F, setar o protótipo desta para o objeto passado como parâmetro e retornar uma instância de F.

    Ou seja, ela devolve um objeto vazio que herda (possui a propriedade __proto__ igual ao) objeto passado!

     // Cria um objeto vazio com prototype igual ao de Pessoa var pessoa = Object.create(Pessoa.prototype); 
    

    Note que, dessa forma, deixamos de dar new em uma Pessoa sem argumentos para criar um objeto vazio com o protótipo de Pessoa, uma cópia!

    Mas nós não queremos uma pessoaFisica que é igual a uma pessoa! Queremos que nosso objeto saiba dizer seu CPF, certo? Para isso, você poderia pensar em adicionar direto no objeto retornado:

     var pessoaFisica = Object.create(Pessoa.prototype); pessoaFisica.dizCpf = function(){ console.log("meuCPF"); } 
    

    Mas assim nós acabamos de perder a vantagem do prototype: vamos definir uma função para cada instância de PessoaFisica.

    O que queremos, então, é definir os métodos da PessoaFisica e da Pessoa utilizando seus prototypes e combiná-los de um modo mais enxuto. Seria bacana uma função que encapsulasse todo esse comportamento, onde você passasse a função pai e a função filha e ela se responsabilizasse por fazer a função filha herdar a função pai, ou seja, combinar seus protótipos! ```js herda(Pessoa, PessoaFisica); // faz PessoaFisica herdar Pessoa

    
    Legal! Então vamos implementar essa função:
    ```js
     var herda = function(mae, filha){ // Faz uma cópia do prototipo da mãe var copiaDaMae = Object.create(mae.prototype);
    // herda mãe filha.prototype = copiaDaMae;
    //Ajusta construtor da filha filha.prototype.constructor = filha; } 
    

    Agora, para herdarmos Pessoa, basta chamar a função herda passando a PessoaFisica e a Pessoa:

     var PessoaFisica = function(nome, email, cpf){ Pessoa.call(this, nome, email); this.cpf = cpf; };
    herda(Pessoa, PessoaFisica); 
    

    Note que mantemos a estrategia de Constructor Stealling pois, sem ela, perderíamos as validações feitas no construtor do pai(como o if(emailEhValido(email))).

    E, em seguida, definir os métodos da PessoaFisica em seu prototype:

     var PessoaFisica = function(nome, email, cpf){ Pessoa.call(this, nome, email); this.cpf = cpf; };
    herda(Pessoa, PessoaFisica);
    PessoaFisica.prototype.dizCpf = function(){ console.log(this.cpf); }; 
    

    Agora, para usar uma PessoaFisica, basta instanciá-la:

     var leonardo = new PessoaFisica("Leonardo", "[email protected]", "meucpf"); leonardo.fala(); // Olá, meu nome é Leonardo e meu email é [email protected] leonardo.dizCpf(); //meucpf 
    

    Perceba que agora, ao contrário da Prototype-chaining Inheritance, nós só chamamos a função Pessoa uma vez: ao instanciar a PessoaFisica.

    Esta estratégia é descrita no livro Professional JavaScript for Web Developers (de Nicholas C. Zakas) como Parasitic Combination, um modo de implementar herança que o próprio Zakas descreveu como "the most optimal inheritance paradigm".

    3 - Functional Inheritance

    Imagine que, em vez de termos uma função construtora e darmos new nela para obtermos um objeto, nós simplesmente retornássemos um objeto utilizando notação literal (esse padrão é explicado aqui):

    Mas como vamos implementar herança sem utilizarmos prototypes?

    Para isso, vamos utilizar uma estratégia um pouco diferente: em vez de adicionarmos os atributos e métodos nas instâncias de pessoaFisica, vamos fazer a função pessoaFisica() devolver uma pessoa() modificada:

     var pessoaFisica = function(nome, email, cpf){ var pessoa = pessoa(nome, email); pessoa.dizCpf = function(){ console.log(cpf); }; return pessoa; } 
    

    Uma observação importante: quando utilizada a Funcional Inheritance, em nenhum momento você vai utilizar o operador new, sendo assim, suas funções não deverão ter nada atribuido à referência this. Caso você utilize o this dentro de uma função e a chame sem o uso da palavra chave new, o this apontará para window, criando variáveis globais!

    Essa é a estratégia chamada de Functional inheritance.

    Para saber mais

    Benchmark

    Para comparar a performance destes três modos, eu escrevi um benchmark verificando 4 situações para cada um deles.

    Os resultados podem ser observados neste gist

    Grande parte das vezes que eu executei o benchmark, realmente a Parasitic Combination Inheritance foi a mais performática!

    Além disso, nos benchmarks onde eu testei a velocidade de instanciação, a Functional Inheritance demorou mais do que o dobro do tempo, comprovando o ganho de performance do uso de prototypes.

    O codigo fonte dos benchmarks podem ser encontrados no meu github

    Banner do Guia Tático Alura sobre carreira em tecnologia, destacando o mapa da carreira tech. A imagem convida a explorar diferentes caminhos profissionais, comparar possibilidades e encontrar a próxima fase da carreira na área de tecnologia, com chamada “Explore o mapa”.

    Avalie este artigo

    • Foto de leonardo.wolter

      Autor(a)

      leonardo.wolter

    Explore por tópico

    • Back-end
    • Dados
    • DevOps
    • Front-end
    • Gestão & Negócios
    • Institucionais
    • Inteligência Artificial
    • Mobile
    • UX & Design

    Leia também

    • 01/09/2024

      Como criar animações incríveis com CSS

      Ler mais
    • 07/08/2017

      Padrão BEM CSS: como criar componentes CSS reutilizáveis usando Block Element Modifier

      Ler mais
    • 09/11/2021

      Tailwind: Adicionando fontes customizadas

      Ler mais
    Ver mais conteúdos

    Inscreva-se em nossa Newsletter

    Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.

    Institucional

    • Sobre nós
    • Trabalhe Conosco
    • Para Empresas
    • Para Escolas
    • Política de Privacidade
    • Compromisso de Integridade
    • Termos de Uso
    • Canal de Ética
    • Código de Ética
    • Fale Conosco
    • Documentos Institucionais
    • Status
    Institucional
    • Sobre nós
    • Trabalhe Conosco
    • Para Empresas
    • Para Escolas
    • Política de Privacidade
    • Compromisso de Integridade
    • Termos de Uso
    • Canal de Ética
    • Código de Ética
    • Fale Conosco
    • Documentos Institucionais
    • Status

    A Alura

    • Como Funciona
    • Inteligência Artificial
    • Plataforma
    • Depoimentos
    • Instrutores(as)
    • Dev em <T>
    • Luri, a Inteligência Artificial da Alura
    • IA Conference
    • Cursos Imersivos
    • Perguntas Frequentes
    A Alura
    • Como Funciona
    • Inteligência Artificial
    • Plataforma
    • Depoimentos
    • Instrutores(as)
    • Dev em <T>
    • Luri, a Inteligência Artificial da Alura
    • IA Conference
    • Cursos Imersivos
    • Perguntas Frequentes

    Conteúdos

    • Alura Cases
    • Imersão Engenharia de Software: Dev na Era da IA
    • Artigos
    • Podcasts
    • Artigos de educação corporativa
    Conteúdos
    • Alura Cases
    • Imersão Engenharia de Software: Dev na Era da IA
    • Artigos
    • Podcasts
    • Artigos de educação corporativa
    Uma Empresa do GrupoLogo Grupo Alun

    Outras empresas do Grupo Alun

    • FIAP
    • STARTSE
    • PM3
    • LUMINA

    Ao submeter seu e-mail, você concorda com a política de privacidade da Alura.

    Redes Sociais & Apps

    instagram
    youtube
    tiktok
    x
    appStore
    googlePlay
    Uma Empresa do GrupoLogo Grupo Alun

    Outras empresas do Grupo Alun

    • FIAP
    • STARTSE
    • PM3
    • LUMINA

    Ao submeter seu e-mail, você concorda com a política de privacidade da Alura.

    Redes Sociais & Apps

    instagram
    youtube
    tiktok
    x
    appStore
    googlePlay
    Alura