Categories: javascripttodas

JavaScript precisa de classes?

Quer você goste ou não, a ECMAScript 6 está prevendo a criação de classes[1] na linguagem JavaScript. O conceito de classes em JavaScript sempre foi um assunto polêmico. Há desenvolvedores que adoram a ausência de classes na JavaScript justamente por fazê-la diferente de outras linguagens. No outro lado estão os desenvolvedores que odeiam a ausência de classes justamente porque a faz diferente de outras linguagens. Um dos maiores obstáculos que as pessoas encontram quando migram de C++ ou Java para JavaScript é a ausência de classes e eu já ouvi muitas pessoas dizer que não gostam de JavaScript ou desistiram de estudar a linguagem por causa da ausência de classes.

Desde que a JavaScript foi criada nunca houve uma definição formal de classes e isso vem gerando confusão desde sua criação. Não são raros os livros e artigos sobre JavaScript falando de classes, como se elas fossem reais na linguagem. O que eles chamam de classes nada mais são do que contrutores personalizados usados para definir tipos de referências personalizados. Tipos de referência em JavaScript são a coisa mais próxima à classes. A sintaxe geral é familiar à maioria dos desenvolvedores, mas aqui vai um exemplo:

function MyCustomType(value) {      
  this.property = value;  
  }    
  
MyCustomType.prototype.method = function() {      
  return this.property;  
  };

Com muita frequência este código é descrito como sendo a declaração de uma classe denominada MyCustomType. Na verdade, tudo o que ele faz é declarar uma função denominada MyCustomType que quando usada com o operador new cria uma instância do tipo de referência MyCustomType. Contudo não há nada especial com esta função que a faça diferente de outras funções não destinadas a criar novos objetos. É o uso da função que a faz um construtor.

O código não se parece com um código definidor de classe. Existe uma tênue relação entre a definição de construtor e o método de protótipo. Desenvolvedores JavaScript iniciantes, acostumados a outras linguagens enxergam dois códigos completamente independentes. Sim, existe uma relação óbvia entre os dois códigos, mas não há nenhuma semelhança com código definidor de classe em outras linguagens.

A confusão aumenta quando as pessoas começam a falar de herança. Herança arrasta consigo os conceitos de sub-classes e super-classes, conceitos estes que só fazem sentido quando existem classes. A sintaxe JavaScript para herança é igualmente confusa e verbosa:

function Animal(name) {      
  this.name = name;  
  }    

Animal.prototype.sayName = function() {      
  console.log(this.name);  
  };    

function Dog(name) {      
  Animal.call(this, name);  
  }    

Dog.prototype = new Animal(null);  

Dog.prototype.bark = function() {      
  console.log("Woof!");  
  };

O processo em duas etapas para definir herança usando um construtor e sobrescrevendo um protótipo é incrivelmente confuso.

Na primeira edição do livro Professional JavaScript for Web Developers usei o termo “class”. Recebi feedback que esse termo estava confundindo os leitores, o que me fez trocar o termo “class” pelo termo “type” na segunda edição do livro. A partir de então passei a usar este termo uma vez que ele evita confusões.

Contudo ainda existe outro problema evidente. A sintaxe para definição de tipos personalizados é também confusa e verbosa. Herança entre dois tipos é um processo multi-etapas. Não existe um mecanismo simples para chamar um método em um super-tipo. Resumo: é uma grande dor de cabeça criar e gerenciar tipos. Se você acha que isso não é um problema observe a quantidade de bibliotecas JavaScript que implementam seus próprios mecanismos de definição de herança e tipos personalizados ou ambos:

  • YUI – Implementou o método Y.extend() para herança. Adicionou uma propriedade super-classe para este método.[2]
  • Prototype – Implementou os métodos Class.create() e Object.extend() para objetos e “classes”.[3]
  • Dojo – Implementou os métodos dojo.declare() e dojo.extend().[4]
  • MooTools – Implementou um tipo personalizado denominado Class para definir e estender classes.[5]

É um sinal óbvio que há problemas quando tantas bibliotecas JavaScript implementam suas próprias soluções. Definir tipos personalizados é uma tarefa confusa e nada intuitiva. Os desenvolvedores JavaScript precisam de uma sintaxe melhor que a atual.

Classes na ECMAScript 6 não são nada mais do que melhorias na sintaxe com a qual você já está familiarizado. Considere o exemplo a seguir:

class MyCustomType {      
  constructor(value) {          
    this.property = value;      
  }        

method() {          
  return this.property;      
  }  
}

Essa é a sintaxe melhorada prevista pela ECMAScript 6 para definição de classe, e, equivalente a sintaxe tradicional mostrada anteriormente. Um objeto criado com uso desta definição de classe é exatamente igual a um objeto criado com o construtor mostrado anteriormente. A única diferença é o uso de uma sintaxe mais compacta.
E quanto a herança:

class Animal {      
  constructor(name) {          
    this.name = name;      
    }        
sayName() {          
  console.log(this.name);      
  }  
}    

class Dog extends Animal {      
  constructor(name) {          
  super(name);      
  }        

bark() {          
  console.log("Woof!");      
  }  
}

Este exemplo melhora o exemplo de herança mostrado anteriomente. A definição de classes é compacta é elimina a necessidade de multi-etapas substituindo-a por uma sintaxe com uso de uma simples palavra-chave. Você ainda tem a vantagem de um super() dentro da definição de uma classe e desta forma não precisa de mais de um mecanismo para fazer referência a um super-tipo

Toda a proposta de classes na ECMAScript 6 nada mais é do que simplificação da sintaxe nas diferentes formas já conhecidas da JavaScript. Herança funciona como sempre funcionou (cadeia de protótipos mais chamada de um construtor super-tipo), métodos são adicionados a protótipos e propriedades são declaradas no construtor. A real diferença é: menos digitação para você. Definição de classes nada mais é do que definição de tipos com uso de sintaxe diferenciada.

Assim enquanto alguns estão se reposicionando porque a ECMAScript 6 está criando classes, tenha em mente que classes é um conceito abstrato. Não há nenhuma alteração no modo como JavaScript funciona, não está se criando nada novo. Classes são apenas melhorias sintáticas naquilo que você já conhece sobre tipos personalizados há um bom tempo. Isso resolve um problema antigo da JavaScript que é a verbosidade e a confusão quando se trata de definir seus próprios tipos. Pesoalmente eu preferiro o uso de palavras-chave para criar tipos em lugar de classes, mas no fim das contas isso é apenas uma questão semântica.

Afinal, JavaScript precisa de classes? Não, mas definitivamente JavaScript precisa de uma forma clara de definir tipos personalizados. E essa forma clara tomou o nome de classes na ECMAScript 6. E, se isso ajuda desenvolvedores de outras linguagens a migrar ou estudar JavaScript, então é uma boa coisa.

Referências (em inglês)

  1. Maximally minimal classes (ECMA)
  2. YUI extend() (YUILibrary)
  3. Prototype Classes and Inheritance (Prototype)
  4. Creating and Enhancing Dojo Classes (SitePen)
  5. MooTools Class (MooTools)

Créditos:

Este artigo é um tradução. O artigo original de autoria de Nicholas C. Zakas foi publicado em: Does JavaScript need classes?

Maujor

View Comments

  • Muito bom o artigo! Amei por isso sou apaixonado por programação.

  • Para quem quer se especializar em criação de sites e layouts é imprescindível o conhecimento nesta área.

  • Ainda tenho algumas dúvidas, mas esse artigo já iluminou as minhas ideias. obrigada

  • Este tutorial sobre de programaçao de javascript me ajudou muito em algumas duvidas e estava em duvidas... obrigado pelas dicas

  • Muito Interessante este conteúdo. Obrigado pelas informações

Share
Published by
Maujor

Recent Posts

Teste seu conhecimento #20

Em 2006 comecei a publicar nesse blog uma série de desafios CSS que consistiam em…

7 anos ago

Teste seu conhecimento #19

Há muito tempo que eu não publico um "Teste seu conhecimento". Esta semana, revendo algumas…

9 anos ago

JavaScript bubbling e capturing

Introdução Elementos da marcação HTML podem ser aninhados uns dentro de outros, criando-se uma cadeia…

10 anos ago

HTML5 – W3C versus WHATWG

HTML5? Web universal? É comum eu me deparar com dúvidas sobre a HTML5 não só…

10 anos ago

Seria esse o futuro das imagens responsivas?

Quem é Tab Atkins Jr? Tab Atkins Jr, um desenvolvedor americano, trabalhou durante muitos anos…

10 anos ago

BrazilJS Conf 2013

Pessoal, a BrazilJS Conf 2013 disponibilizou para o Maujor cupons de desconto para serem oferecidos…

11 anos ago