Logo do siteSilhueta da face do Maujor seguida do texto Maujor o dinossauro das CSS

Menu hamburger Três barras horizontais na cor laranja destinadas a ser clicada para abrir o menu menu do site

Você está no BLOG do Maujor. IR PARA O SITE

JavaScript precisa de classes?

Publicado em: 2012-10-19 — 13.486 visualizacoes

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?

Livros do Maujor

Desenvolvimento com Padrões Web? Adquira os livros do Maujor
Clique a "capinha" para visitar o site do livro.

capa livro Grid Layout   capa livro html5   capa livro css3   capa livro HTML5 e CSS3   capa livro RWD   capa livro jQuery   capa livro Bootstrap3   capa livro ajaxjQuery   capa livro css   capa livro html   capa livro javascript   capa livro jQuery Mobile   capa livro jQuery UI   capa livro SVG   capa livro foundation   capa livro Sass e Compass

Esta matéria foi publicada em: 2012-10-19 (sexta-feira). Subscreva o feed RSS 2.0 para comentários.
Comente abaixo, ou link para http://www.maujor.com/blog/2012/10/19/javascript-precisa-de-classes/trackback no seu site.

7 comentários na matéria: “JavaScript precisa de classes?”

  1. RodrigoNo Gravatar disse:

    Depois que comecei a entender o Javascript a fundo que comecei a enteder as coisa como funciona realmente

  2. RodrigoNo Gravatar disse:

    Só comecei a entender Jquery de verdade depois que estudei Javascript a fundo. Obrigado por compartilhar

  3. YuriNo Gravatar disse:

    Isso é muito confuso, javascript é mesmo orientada a objetos?
    Uma função dentro de uma classe em java é uma ação que pode ser reproduzida por um objeto do tipo da classe na qual ele se encontra. Agora o javascript vem me falar que eu defino um objeto por uma função… dai eu penso em um construtor e em atributos e me confundo mais ainda !! Dor de cabeça isso… =/

  4. MarcusNo Gravatar disse:

    Pois é, orientação a objetos em JavaScript é confuso. Não tem nada de errado em ser diferente de C++/C#/Java, mas cairia bem uma solução mais completa e mais coesa.

    Conheci esse tipo de orientação a objetos e herança quando aprendi a linguagem brasileira Lua, que usa um princípio bastante semelhante. Curiosamente, antes disso, foi justamente JavaScript que me fez entender orientação a objetos em geral quando vi um str.length!

    Mas como eu disse antes, herança JavaScript seria bem melhor se as pecinhas colaborassem mais entre si. Já li vários tutoriais tentando explicar que depois de setar um prototype, é preciso restaurar a propriedade “constructor”, enquanto outros nem mencionam isso. Outros, mais modernos, dizem que devemos usar Object.create() em vez de construir um objeto com new para ser usado como prototype dos outros.

    Ou seja, parece que temos um kit de peças “monte sua orientação a objetos”: new, this, instanceof, .call() para manipular o this, Object.create(), prototypes. Mas aí a gente vai montar e se depara com coisas faltando, coisas mal explicadas, e fica tentando encontrar o jeito “definitivo” que permitirá simplesmente expressar a intenção do código, e não uma confusa manipulação de this e prototypes.

  5. Gabriel MendonçaNo Gravatar disse:

    Realmente acho que seria muito melhor se essa linguagem maravilhosa contivesse a familiar Class construtora. Porém acho que a dificuldade das pessoas em entender o formato de uma classe em javascript não vem só da problemática de sua sintaxe e sim da falta de conhecimento do conceito abstrato de classes e objetos!

  6. Eduardo AlmeidaNo Gravatar disse:

    realmente bem mais prático …

    na lista de bibliotecas eu incluiria o Joose, que é exclusivamente um sistema de meta objetos para javascript fantástico .. http://code.google.com/p/joose-js/

  7. Rogerio Alencar FilhoNo Gravatar disse:

    Saber Javascript puro ajuda a entender melhor os frameworks, esse exemplo ai, fica bem claro na hora de aplicar no Ext.define e Ext.create do ExtJS.

Comentário:





Teclar "Enter" cria um novo parágrafo. Teclar "Shift + Enter" causa uma quebra de linha.

Subscribe without commenting

topo