Embora o Javascript (em sua essência) seja orientado a objetos, temos que admitir que ela foge um pouco do convencional através do estilo de escrita prototype. Quero dizer que, é possível utilizarmos conceitos como encapsulamento, herança, atributos e métodos públicos e privados, etc. Mas de uma maneira um pouco diferente se comparada a linguagens como Python ou PHP.
A linguagem é composta por alguns objetos muito utilizados no cotidiano,
como os objetos Array
, Math
e String
. Estes (e outros
objetos de core) são instâncias do objeto Object
, que você
pode representar através da seguinte expressão:
var meuObjeto = {};
typeof meuObjeto; // object
typeof Math; // object
Você encontrará uma forma (muito bacana por sinal) de construir objetos através de expressões como essas:
var fooBar = {
init: function() {
console.log("Posso funcionar como um inicializador!");
},
_private: function(tipo) {
console.log("Testando chamada " + tipo + ".");
},
eggs: function() {
console.log("Eggs.");
fooBar._private("interna");
},
spam: function(msg) {
console.log("Spam: " + msg + ".");
},
};
fooBar.init(); // Posso funcionar como um inicializador!
fooBar.eggs(); // Eggs.
// Testando chamada interna
fooBar._private("externa");
// Testando chamada externa
fooBar.spam("Eggs and Spam"); // Spam: Eggs and Spam
Pode-se observar que é uma prática válida para organizar código através de namespaces.
Referência: Using Objects to organize your code
Já utilizei algumas vezes o modelo acima… mas devo dizer que sou adepto a uma outra forma de construirmos classes em Javascript:
var Pessoa = function() {
console.log("Pessoa instanciada!");
};
Pessoa(); // Pessoa instanciada!
console.log(typeof Pessoa); // function
var pessoa1 = new Pessoa(); // Pessoa instanciada!
console.log(typeof pessoa1); // object
No exemplo acima, podemos reparar que seguindo o comportamento normal de
uma função, não há surpresas na execução da expressão Pessoa
. Porém,
quando adicionamos o operador new
na frente, o Javascript cria uma
instância do tipo Pessoa
. Basicamente é como se a expressão
function
fosse “multiuso”, sendo útil para definir funções e
classes.
O mais legal disso é que, como você já deve ter reparado, com o uso do
new
ganhamos de graça um constructor
(ou inicializador, como
preferir) em nossa classe Pessoa
.
Referência: Introduction to Object-Oriented Javascript
Do construtor em diante, já me deparei com algumas vertentes de implementações do Javascript. Já encontrei algumas bem simples, outras um pouco mais complicadas … vou mostrar aqui a que eu acredito ser a mais usual. Não tenho propriedade para dizer se é o modo certo ou mais elegante, apenas é o modo que incorpora características de OOP que melhor me atendeu:
var Linguagem = function(nome, versao) {
this.nome = nome;
this.versao = versao;
};
Acima temos a construção da classe Linguagem
. Em seu constructor
aproveitamos para setar alguns atributos, como nome
e versao
, que são
passados imediatamente na hora de instanciá-la.
Para criar um método para esta classe, vamos recorrer ao prototype do Javascript:
Linguagem.prototype.descricaoCompleta = function() {
return this.nome + " vr. " + this.versao;
};
Resumidamente, estamos adicionando um método de instância na estrutura
da classe. Fazemos isso adicionando uma função ao prototype
da classe.
Dessa forma o método terá acesso as propriedades do objeto na hora que
for instanciado.
Se tentarmos executar a expressão Linguagem.descricaoCompleta
,
iremos nos deparar com um erro de método inexistente. Mas, se
instanciarmos a classe veremos que o método está acessível:
var python = new Linguagem("Python", "2.7");
console.log(python); // Linguagem
console.log(python.descricaoCompleta()); // Python vr.2.7
Acima utilizamos o conceito de métodos e atributos de instância. Através do modelo object literal podemos ter um comportamento parecido com o conceito de métodos de classe:
var Linguagem = function(nome, versao) {
this.nome = nome;
this.versao = versao; // Chamando um método que está fora do prototype da classe
this.meuId = Linguagem.incId();
};
// Adicionando uma propriedade através de Object Literal
Linguagem.id = 0;
// Adicionando um método através de Object Literal
Linguagem.incId = function() {
this.id++;
return this.id;
};
var javascript = new Linguagem("Javascript", "1.5");
console.log(javascript); // Linguagem
console.log(javascript.meuId); // 1
Esta forma de criar classes e objetos em Javascript é executada com muito sucesso na biblioteca RGraph.
Referências: Javascript is Object Oriented Programming
Para entender como criar heranças com o prototype do Javascript,
vamos primeiramente criar um tipo chamado Framework
:
var Framework = function(nomeFramework, nome, versao) {
this.nome = nome;
this.versao = versao;
this.nomeFramework = nomeFramework;
};
No caso acima, iremos sobrescrever o comportamento do constructor da
classe Linguagem
.
E é aqui que a mágica acontece… instanciamos o tipo Linguagem
no
prototype
da classe Framework
. Isto fará com que o tipo
Framework
possua todas as propriedades de Linguagem
. Depois corrigimos
o constructor
, apontando ele novamente para Framework
:
// Cria herança com Linguagem
Framework.prototype = new Linguagem();
// Corrige o ponteiro do constructor para Framework (está apontando para Linguagem)
Framework.prototype.constructor = Framework;
Vamos adicionar um método exclusivo da classe Framework
:
Framework.prototype.feitoEm = function() {
return this.nomeFramework + " é feito em " + this.nome;
};
Instanciamos algumas vezes a classe Framework
, e teremos o
comportamento esperado de uma herança:
var django = new Framework("Django", "Python", "2.7");
console.log(django); // Framework
console.log(django.descricaoCompleta()); // Python vr.2.7
console.log(django.feitoEm()); // Django é feito em Python
var jquery = new Framework("jQuery", "Javascript", "1.5");
console.log(jquery); // Framework
console.log(jquery.descricaoCompleta()); // jQuery vr.1.5
console.log(jquery.feitoEm()); // jQuery é feito em Javascript
Existem algumas bibliotecas (como a Mootools) que facilitam a criação de classes e heranças em Javascript.
O exemplo completo está disponível para download em: http://github.com/kplaube/post-javascript-oop
Até a próxima…