Olá pessoal, tudo certo?
JavaScript vem ganhando relevância no desenvolvimento de aplicações. Por causa disso, é importante saber como usar essa linguagem de forma refinada. Se possível, com orientação a objetos.
No post de hoje, mostro os fundamentos de orientação a objetos usando JavaScript.
Antes de começar …
JavaScript não foi projetada para ser uma linguagem orienta a objetos. Além disso, há quem diga que pensar a linguagem dessa forma gere alguma confusão.
Alguns dos princípios de design a orientação a objetos podem ser aplicados, mas não todos.
Criando uma classe
Definir uma classe em JavaScript é tão simples quanto escrever uma função. Observe:
function Person() { } var p = new Person();
Só isso! Bacana, não!?
Sintaxe alternativa:
var Person = function () { } var p = new Person();
Definindo um construtor
Um construtor é um código opcional que pode ser executado quando uma instância de objeto é criada.
Dada essa breve explicação (momento pândego … ;-D ), em JavaScript um construtor pode ser definido pela simples adição de código na função que define a classe. Observe:
function Foo() { alert("Hello world from Foo constructor"); } var f = new Foo();
Podemos passar parâmetros para o construtor facilmente. Observe:
var Foo = function (p) { alert("Foo constructor received " + p + " as p value"); } var f = new Foo(2);
Definindo atributos públicos
Atributos públics são definidos junto com a classe, usando a palavra-chave [reservada] this. Repare:
var Foo = function () { this.name = ""; } var f1 = new Foo(); f1.name = "Elemar Jr"; var f2 = new Foo(); f2.name = "Gabriel Severo"; alert("f1.name = " + f1.name + "\nf2.name = " + f2.name);
Combinando com construtores:
var Foo = function (name) { this.name = name; } var f1 = new Foo("Elemar Jr"); var f2 = new Foo("Gabriel Severo"); alert("f1.name = " + f1.name + "\nf2.name = " + f2.name);
Legal.
Definindo métodos
Agora, vamos ver como definir métodos. Como tudo em JavaScript, é bem simples. Observe:
var Foo = function (name) { this.name = name; this.sayHello = function () { alert("Hello from " + this.name); } } var f1 = new Foo("Elemar Jr"); var f2 = new Foo("Gabriel Severo"); f1.sayHello(); f2.sayHello();
Como pode ser observado, um método é definido de forma semelhante a um atributo.
Pausa para conhecer a palavra-chave prototype
Outra forma de definir propriedades e métodos para uma classe ocorre fora da definição. Isso, através da palavra-chave prototype. Observe:
var Foo = function (name) { this.name = name; } Foo.prototype.sayHello = function () { alert("Hello from " + this.name); }; var f1 = new Foo("Elemar Jr"); var f2 = new Foo("Gabriel Severo");
Belo, não!?
Que tal um Singleton?
Se você usa orientação a objetos, então, deve conhecer Singleton. Em JavaScript, há mais de uma forma de implementar Singleton. Olhe que fácil:
var FooSingleton = new function () { this.sayHello = function () { alert("Hello from a true singleton!"); }; } (); FooSingleton.sayHello();
Singleton com JSON
Outra forma bacana de criar um singleton é usando JSON. Observe:
var FooSingleton = { name: "", sayHello: function () { alert("Hello from " + name); } } FooSingleton.name = "Elemar JR"; FooSingleton.sayHello();
Implementando Herança (com polimorfismo)?! Sim senhor, senhor!
Quer construir uma especialização de uma classe em JavaScript?! É possível. Repare:
var BaseFoo = function () { this.name = ""; this.sayHello = function () { alert("Hello from BaseFoo (name = " + this.name + ")"); }; }; var Foo = function () { }; Foo.prototype = new BaseFoo(); Foo.prototype.constructor = Foo; var f = new Foo(); f.name = "Elemar JR"; f.sayHello();
Vamos a receita de bolo:
- Tenha uma classe base;
- Crie uma classe vazia;
- Herde as propriedades e métodos da classe base usando uma instância como protótipo;
- Redefina o construtor.
Lindo!
Agora, o polimorfismo:
var BaseFoo = function () { this.name = ""; this.sayHello = function () { alert("Hello from BaseFoo (name = " + this.name + ")"); }; }; var Foo = function () { }; Foo.prototype = new BaseFoo(); Foo.prototype.constructor = Foo; Foo.prototype.sayHello = function () { alert("Hello from Foo! (name = " + this.name + ")"); } var f = new Foo(); f.name = "Elemar JR"; f.sayHello();
Óbvio e simples.
Criando atributos e métodos “privados”
Todos os métodos e atributos que definimos até aqui são públicos. Para garantir um acesso “quase privado” a atributos e propriedades, devemos utilizar a palavra-chave var no lugar de this. Observe:
var Foo = function () { var name = ""; this.getName = function () { return name; } this.setName = function (value) { name = value; } this.sayHello = function () { alert("Hello from BaseFoo (name = " + this.getName() + ")"); }; }; var f = new Foo(); f.setName("Elemar JR"); f.sayHello();
name é privado.
Definindo Namespaces
Ninguém quer poluir o global scope. Esta prática, além de “suja” é perigosa pois o JavaScript não vai dar qualquer warning quando uma variável tiver seu valor substituído de alguma forma.
A solução para este problema é criar uma variável no global scope que atua como um literal (objeto JSON) ou singleton contendo todo o código da aplicação.
Um exemplo simples:
var myNamespace = new function () { this.Cool = { Foo: function () { this.name = ""; this.sayHello = function () { alert("Hello from " + name); } } } } (); var foo = new myNamespace.Cool.Foo(); foo.name = "Elemar JR"; foo.sayHello();
Por hoje, era isso!
Thiago
20/09/2011
Show de bola esse post Elemar! Parabéns!
elemarjr
20/09/2011
Muito obrigado, man
20/09/2011
Muito bom, a um mês atrás iniciei um projeto free e utilizei praticamente tudo que você apresentou aqui, foi fácil e ficou BEM mais elegante! Utilizando o firebug então…
O mais difícil foi chegar no serviço e mostrar para os colegas e tentar convencer que era melhor que usar scrips associadas ao “window” e totalmente estático.
Abraço.
Cristian Mathias
elemarjr
20/09/2011
Obrigado, man.
Como eu sempre digo, o mais difícil é SEMPRE convencer os colegas. Nunca o chefe!
Denis Martins
21/09/2011
Parabéns, Elemar! Muito bom o post e muito útil.
elemarjr
20/09/2011
Obrigado Denis
Guilherme
28/09/2011
Bacana. Ao mesmo tempo que achei interessante, achei estranho demais..não consigo explicar, mas algumas coisas aí não achei legal.
Mas meus parabéns pelo artigo, bem explica e direto no assunto.
Pedro Marques
06/10/2011
Muito bom!!!!! Como ja foi dito bem mais elegante e legivel.
Danilo
11/10/2011
muito bom, eu estudo javascript mas não tinha o hábito de chamar uma função de Classe, e e me parece que vc usou um conceito supondo conhecendo outra linguagem, e o OOP mas conseguir entender um pouquinho. :>
elemarjr
11/10/2011
Opa, Apenas tentei aplicar os conceitos de OO