- Adicionando propriedades e métodos a um objeto vazio:
<script type="text/javascript">
function criarUsuario(nome, contato){ //Função construtora
var objeto = new Object();
objeto.nome = nome;
objeto.contato = contato;
objeto.exibirNome = function(){
alert("Meu nome é:"+this.nome);
}
objeto.exibirContato=function(){
alert("Meu contato é:"+this.contato);
}
return objeto;
}
var usuario1 = criarUsuario("Ana","123456789");
usuario1.exibirNome();
usuario1.exibirContato();
var usuario2 = criarUsuario("Carlos","987654321");
usuario2.exibirNome();
usuario2.exibirContato();
/*
* A abordagem de fábrica acima tem desvantagens: cada vez que um objeto é criado,
* suas próprias funções são criadas. Se forem criados muitos usuários,
* isso resultará em muitas funções duplicadas e consumo excessivo de memória;
*/
</script>
A função criarUsuario acima é chamada de função construtora apenas porque sua função é construir um objeto, não havendo diferença com funções comuns;
No entanto, essa abordagem tem duas desvantagens:
- Não utiliza a palavra-chave
new; - Cada objeto criado tem suas próprias funções. Se forem criados centensa ou milhares de usuários, as funções se repetirão, consumindo recursos do sistema e gerando desperdício.
- Resolvendo a falta da palavra-chave
new:
<script type="text/javascript">
function criarUsuario(nome, contato){ //Função construtora
//O sistema secretamente faz:
//var this = new Object();
this.nome = nome;
this.contato = contato;
this.exibirNome = function(){
alert("Meu nome é:"+this.nome);
}
this.exibirContato=function(){
alert("Meu contato é:"+this.contato);
}
//O sistema também secretamente faz:
//return this;
}
var usuario1 = new criarUsuario("Ana","123456789");
usuario1.exibirNome();
usuario1.exibirContato();
var usuario2 = new criarUsuario("Carlos","987654321");
usuario2.exibirNome();
usuario2.exibirContato();
</script>
- Resolvendo o desperdício de recursos;
Antes de resolver o desperdício de recursos, vamos introduzir o conceito de prototype:
Prototype:
CSS JS
Classe Aplica estilos a um grupo de elementos Prototype
Estilo inline Aplica estilos a um único elemento Adiciona propriedades a objetos
.box{background:red;}
<div class="box" style="background:green;"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
Vamos a um exemplo: arrays não possuem um método de soma. Vamos criar um:
<script type="text/javascript">
var array1 = new Array(1,2,45,34);
var array2 = new Array(1,2,33);
array1.somar=function(){
var resultado = 0;
for(var i=0; i<this.length; i++){
resultado+= this[i];
}
return resultado;
}
alert(array1.somar());
//alert(array2.somar()); //Iria gerar erro
</script>
No entanto, apenas o array1 possui o método somar, pois adicionamos o método apenas a este objeto específico, similar a um estilo inline;
Para que array2 também tenha o método somar, fazemos o seguinte:
<script type="text/javascript">
var array1 = new Array(1,2,45,34);
var array2 = new Array(1,2,33);
Array.prototype.somar=function(){
var resultado = 0;
for(var i=0; i<this.length; i++){
resultado+= this[i];
}
return resultado;
}
alert(array1.somar());
alert(array2.somar());
</script>
Aplicando o conceito de prototype à programação orientada a objetos: transformamos criarUsuario em uma classe Usuario:
<script type="text/javascript">
function Usuario(nome, contato){ //Função construtora
this.nome = nome;
this.contato = contato;
}
Usuario.prototype.exibirNome= function(){
alert("Meu nome é:"+this.nome);
}
Usuario.prototype.exibirContato = function(){
alert("Meu contato é:"+this.contato);
}
var usuario1 = new Usuario("Ana","123456789");
usuario1.exibirNome();
usuario1.exibirContato();
var usuario2 = new Usuario("Carlos","987654321");
usuario2.exibirNome();
usuario2.exibirContato();
alert(usuario1.exibirNome == usuario2.exibirNome); //true, ambos compartilham o mesmo método
</script>
Use construtores para adicionar propriedades;Use prototypes para adicionar métodos; Similar a Array, Date, etc., que não são funções comuns, mas sim construtores. O nome da classe geralmente começa com letra maiúscula. Por isso, renomeamos para Usuario; 4. Abordagem JSON para programação orientada a objetos: JSON:SimplesNão adequado para múltiplos objetosSingleton; Não adequado para classes como Usuario que precisam criar múltiplas instâncias;Mas adequado para casos como requisições AJAX, onde apenas uma instância é necessária; JSON: Único em toda a aplicação. Mais simples de escrever. Pode ser usado como namespace; Por exemplo, múltiplas funções chamadas getUser: json.common.getUser; json.fx.getUser; json.site.getUser, etc.```
5. Herança em JavaScript: Herança: Propriedades e métodos da classe paiComo herdar as propriedades da classe pai? Primeiro, vamos falar sobre o método call;```
<script type="text/javascript">
function exibir(){
alert(this);
}
//exibir(); //window
//exibir.call(); //Mesmo resultado acima; window
//Mas tem uma diferença: pode alterar o 'this' interno
//exibir.call(12); // 12
function exibir2(a, b){
alert("this é:"+this+"\na é:"+a+"\nb é:"+b);
}
//exibir2(12,5); //this é window a é 12 b é 5
exibir.call('abc', 12, 5); //this é abc a é 12 b é 5
</script>
Exemplo de herança:
<script type="text/javascript">
function ClassePai(){
this.propriedade = 12;
}
ClassePai.prototype.metodo=function(){
alert(this.propriedade);
}
//Herda ClassePai
function ClasseFilha(){
//this->new ClasseFilha()
ClassePai.call(this);
}
ClasseFilha.prototype=ClassePai.prototype;
</script>
ClassePai.call(this) faz com que ClasseFilha herde as propriedades de ClassePai;
ClasseFilha.prototype=ClassePai.prototype; faz com que ClasseFilha herde os métodos de ClassePai;
No antanto, essa abordagem de herança pode ter problemas:
ClasseFilha pode ter não apenas métodos herdados de ClassePai, mas também seus próprios métodos;
<script type="text/javascript">
function ClassePai(){
this.propriedade = 12;
}
ClassePai.prototype.metodo=function(){
alert(this.propriedade);
}
//Herda ClassePai
function ClasseFilha(){
//this->new ClasseFilha()
ClassePai.call(this);
}
ClasseFilha.prototype=ClassePai.prototype;
ClasseFilha.prototype.outroMetodo=function(){
alert('abc');
}
var objFilho = new ClasseFilha();
var objPai = new ClassePai();
//Funciona corretamente, mas objPai não deveria ter outroMetodo
//Isso acontece porque ClasseFilha.prototype=ClassePai.prototype faz com que ambos apontem para o mesmo objeto
objPai.outroMetodo();
</script>
Como corrigir este problema? Veja abaixo:
<script type="text/javascript">
function ClassePai(){
this.propriedade = 12;
}
ClassePai.prototype.metodo=function(){
alert(this.propriedade);
}
//Herda ClassePai
function ClasseFilha(){
ClassePai.call(this);
}
for(var i in ClassePai.prototype){
ClasseFilha.prototype[i] = ClassePai.prototype[i];
}
ClasseFilha.prototype.outroMetodo=function(){
alert('abc');
}
//Teste
var objFilho = new ClasseFilha();
var objPai = new ClassePai();
objFilho.metodo(); //12
objFilho.outroMetodo(); //abc
objPai.outroMetodo(); //Erro
</script>