Construtores em JavaScript

(Última atualização em: 1 de agosto de 2016)

Criar um objeto em JavaScript é bem tranquilo:

var produto1 = {
    nome: "Blusa",
    preco: 120,
    calculaDesconto: function(){
        return this.preco * 0.1; //10% de desconto
    }
};
produto1.calculaDesconto(); //12

Como faríamos pra ter um segundo produto, com o mesmo cálculo de desconto? Assim:

var produto1 = {
    nome: "Blusa",
    preco: 120,
    calculaDesconto: function(){
        return this.preco * 0.1; //10% de desconto
    }
};
var produto2 = {
    nome: "Calça",
    preco: 300,
    calculaDesconto: function(){
        return this.preco * 0.1; //10% de desconto
    }
};
produto1.calculaDesconto(); //12
produto2.calculaDesconto(); //30

Puxa… Perceba que repetimos exatamente o mesmo código no método calculaDesconto para os dois produtos. Além disso, repetimos o nome dos outros atributos, correndo o risco de digitá-los errados.

Como resolver isso?
E se pegassemos a estrutura comum dos produtos (ter nome, preço e poder calcular desconto) e colocássemos em uma função criaProduto?
Algo como:

function criaProduto(paramNome, paramPreco){
    return {
        nome: paramNome,
        preco: paramPreco,
        calculaDesconto: function(){
            return this.preco * 0.1; //10% de desconto
        }
    };
}
var produto1 = criaProduto("Blusa", 120);
var produto2 = criaProduto("Calça", 300);
produto1.calculaDesconto(); //12
produto2.calculaDesconto(); //30

Perceba que na função criaProduto retornamos um objeto que terá sempre os nomes de atributos. Além disso, não repetimos o código da função de desconto 🙂

Interessante! E o mais bacana é que o JavaScript já vem com uma sintaxe para definir a estrutura comum entre os objetos:

function Produto(paramNome, paramPreco){
    this.nome = paramNome;
    this.preco = paramPreco;
    this.calculaDesconto = function(){
        return this.preco * 0.1; //10% de desconto
    };
}
var produto1 = new Produto("Blusa", 120);
var produto2 = new Produto("Calça", 300);
produto1.calculaDesconto(); //12
produto2.calculaDesconto(); //30

Observe que:

  • não precisamos retornar nada
  • as propriedades são definidas com this
  • é usado = ao invés de : para atribuir
  • as linhas são separadas por ;
  • ao criar os produtos usamos o new

A sintaxe anterior é a maneira correta de definir a estrutura para seus objetos e é chamada de construtor. Essa estrutura comum dos objetos muitas vezes é chamada de classe.

Na nova versão da linguagem JavaScript, o EcmaScript 2015, há uma outra maneira de criar um construtor (e a classe):

class Produto {
  constructor(paramNome, paramPreco){
    this.nome = paramNome;
    this.preco = paramPreco;
  }
  calculaDesconto() {
     return this.preco * 0.1;
  }
}
var produto1 = new Produto("Blusa", 120);
var produto2 = new Produto("Calça", 300);
produto1.calculaDesconto(); //12
produto2.calculaDesconto(); //30

Repare que:

  • temos uma class, e não mais uma function
  • definimos os atributos dentro de constructor
  • o método calculaDesconto fica a parte, sem o this

A parte chata é que essa última maneira não funciona ainda na maioria dos browsers… No Chrome, você pode habilitar o suporte a EcmaScript 2015 em: chrome://flags/#enable-javascript-harmony. Infelizmente, mesmo habilitando não funcionará no Console, apenas em código de arquivos .js.

Atualização
Desde a versão 49 do Chrome, lançada em Março/2016, a sintaxe de classes já vem habilitada por padrão!

A linguagem Javascript tem vários recursos poderosos. Nossos cursos de Javascript do Alura e a Formação Front-End da Caelum podem te ajudar a aprofundar nessa linguagem 🙂

  • Muito interessante, esta cada vez mais parecido com java.

    Existe algum prazo para inicio do suporte a essa nova sintaxe nos browsers nos navegadores ?

    • Matheus, não tenho informação sobre o prazo em que o EcmaScript 2015 já virá habilitado. Mas há algumas tabelas de compatibilidade que mostram como está o andamento da implementação: https://kangax.github.io/compat-table/es6/

      Um opção é usar uma ferramenta que transforma código que usa recursos novos do JavaScript em código compatível com os navegadores atuais. Uma dessas ferramentas é o Babel: https://babeljs.io/

    • Matheus,

      Parece que desde o Chrome 49, lançado em março de 2016, essa funcionalidade vem habilitada por padrão:
      https://www.chromestatus.com/feature/4633745457938432

      Várias outras funcionalidades do ES6 já estão sendo suportadas. De acordo com a tabela de compatibilidade que mencionei anteriormente, na versão atual (52), 97% do ES6 está implementado.

Próximo ArtigoCriando uma lista com ListView no Android