JavaScript precisa de classes?
Publicado em: 2012-10-19 — 190.692 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()
eObject.extend()
para objetos e “classes”.[3] - Dojo – Implementou os métodos
dojo.declare()
edojo.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)
- Maximally minimal classes (ECMA)
- YUI extend() (YUILibrary)
- Prototype Classes and Inheritance (Prototype)
- Creating and Enhancing Dojo Classes (SitePen)
- 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?
Desenvolvimento com Padrões Web? Adquira os livros do Maujor
Visite o site dos livros.
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 https://www.maujor.com/blog/2012/10/19/javascript-precisa-de-classes/trackback no seu site.
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.
Show de bola !!! Ótimo conteúdo para o leitor.
Isso sim é uma bela de uma explicação, no detalhe! Show
Esse tutorial me ajudou muito, valeeeu
Ainda tenho algumas dúvidas, mas esse artigo já iluminou as minhas ideias. obrigada
Finalmente um texto esclarecedor. obrigado
Obrigado pelas dicas, aprendi muito sobre o assunto
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
Demorei mas consegui dominar tudo isso.
Eu só utilizo dessa forma.
Não acho que precise de mais que isso.
Enteder de javascript é fundamental, com esse modelo fica bem mais facil
Eu demorei bastante a conseguir entender mas depois que a gente engrena fica tudo mais fácil.
Não desistam e sigam estudando que o resultado vem.
[…] you adored this article and you also would like to get more info pertaining to Site – http://Www.maujor.com, generously visit our own internet site. Cursos Ministrados: (D. Ministrou aulas de informática e […]
Depois que comecei a entender o Javascript a fundo que comecei a enteder as coisa como funciona realmente
Só comecei a entender Jquery de verdade depois que estudei Javascript a fundo. Obrigado por compartilhar
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… =/
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.
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!
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/
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.