No capítulo anterior sobre Orientação a Objetos você aprendeu a utilizar uma função, que também é um objeto, na criação de um construtor. Também foi visto o conceito de construtor, métodos e propriedades apesar de não constar na especificação do Ecma o conceito de métodos.
Abordaremos hoje o início do conceito de “Herança Prototípica” no JavaScript.
Respeitando os padrões aprendidos no capítulo anterior sobre JOOP aqui do TutsMais, vamos criar um construtor ou uma função construtora vazia:
function TutsMais() {}
Agora vamos utilizar esse construtor, extender e acrescentar um valor ou propriedade ao nosso construtor:
TutsMais.prototype.carro = function() {
alert( "Teste" );
}
// Aproveitando pra relembrar o nosso Creational Pattern
var Objeto = new TutsMais();
Agora vamos ver o resultado disso no console.log() (ctrl + shift + j , chrome) :

Humm que tal? Você já conseguiu entender?
Antes de dar continuidade vou explicar mais um conceito de Orientação a Objetos. O “Instanciar”, como você mesmo pode observar, corresponde a criação física e concreta do Modelo ou da Função Construtora TutsMais.
Agora que você conhece cada membro de uma herança, e já consegue fazer uma herança de uma função construtora, vamos tentar criar uma herança usando uma palavra reservada no JavaScript, o “this”:
function TutsMais() {
this.PropriedadeA = "Verde";
}
TutsMais.prototype.cores = function() {
return this;
}
var Objeto = new TutsMais();
console.log( Objeto.cores() );
Resultado:

Você já deve estar imaginando o que aconteceu não é? Na função construtora “TutsMais” nós agregamos ou fizemos uma herança usando a propriedade com o prototype “cores” e adicionamos ao Objeto “this” a PropriedadeA: “Verde” . Retornamos o “this” na “herança prototypica” logo abaixo, que agora passou a possuir a PropriedadeA: “Verde”.
“This” é a representação física do Objeto que criamos dentro da construtora e da “herança prototípica” que criamos.
Agora vamos usar uma variação, mas que faz e tem o mesmo resultado da herança anterior:
function TutsMais( PropriedadeA ) {
this.PropriedadeA = PropriedadeA;
}
TutsMais.prototype.cores = function() {
return this;
}
var Objeto = new TutsMais( "Verde" );
console.log( Objeto.cores() );
A única diferença dessa herança, pra anterior, é que passamos o valor do Objeto “Propriedade A” ou setamos o valor do “This” ( Objeto ), já como parâmetro da função, na hora que instanciamos o Objeto com o “This”.
Simplificando:
function Modelo( objeto ) {
this.objeto = objeto; // Objeto this é igual ao "valordoobjeto"
}
Modelo.prototype.propriedade = function() {
return this; // This possui e herda o "valordoobjeto" da construtora
}
var Objeto = new Modelo( "valordoobjeto" ); // Passamos o valor do Objeto
console.log( Objeto.propriedade() ); // Chamamos a herança prototípica que retorna o "this"
Com isso, praticamente aprendemos a criar uma herança clássica e prototípica em JavaScript.
Vamos brincar mais um pouco?
Exemplo 1:
/*
* Emulando a Classe Cachorro no JavaScript
*/
function Cachorro( osso, latido ) {
this.osso = osso;
this.latido = latido;
}
Cachorro.prototype.morder = function() {
return ( "Morde o osso: " + this.osso );
}
Cachorro.prototype.latir = function() {
return ( "Late assim: " + this.latido );
}
// Vamos chamar o nosso Cachorro de Rex
var Rex = new Cachorro( "osso grande!", "au au" );
// Nosso Rex vai Latir e Morder agora, são as duas ações ;D
console.log( Rex.latir() + " " + Rex.morder() );
Exemplo 2:
// Variação da Classe Cachorro
var Cachorro = function( osso, latido ) {
this.osso = osso;
this.latido = latido;
}
Cachorro.prototype.morder = (function() {
return ( "Morde o osso: " + this.osso );
})
Cachorro.prototype.latir = function() {
return "Late assim: " + this.latido;
}
var Rex = new Cachorro( "Osso!", "au au" );
console.log( Rex.morder() + " " + Rex.latir() );
Exemplo 3:
/*
* Emulando a Classe Carro no JavaScript
* Aqui Homenageio um dos meus mestres
*/
function Carro( modelo ) {
this.modelo = modelo;
this.cor = "prata";
this.ano = "2012";
// Aqui crio um gerador de informações.. ;D
this.getInformacao = function() {
return this.modelo + " " + this.ano;
};
}
Carro.prototype.andar = function() {
return "Eu ando de: " + this.modelo + ", sempre que eu tô com preguiça de andar a pé..";
}
Carro.prototype.pintar = function() {
return "Eu tenho um carro na cor: " + this.cor;
}
var meuCarro = new Carro( "Fusca" );
// Gerar informações do Fusca:
console.log( meuCarro.getInformacao() ); // Fusca 2012 ;D
/*
* Essa informação está errada, meu fusca é de 1990, eu posso
* alterar essa informação aqui fora..
* Observe.. ;D
*/
meuCarro.ano = "1990";
// Vamos gerar novamente essas informações sobre o meu fusca
console.log( meuCarro.getInformacao() ); // Fusca 1990 ;D
// Chamando os protótipos..
console.log( meuCarro.andar() ); // Eu ando de: Fusca, sempre que eu tô com preguiça de andar a pé..
console.log( meuCarro.pintar() ); // Eu tenho um carro na cor: prata
// Se eu quiser criar outro carro? Posso?
var meuCarro = new Carro( "Ferrari" );
// Essa é a famosa herança em JavaScript. Com reutilização de código.
console.log( meuCarro.getInformacao() );
Exemplo 4:
/*
* Vamos Emular Mulheres?
* Como representaríamos mulheres em JS?
*/
var Mulheres = (function( idade, cor, altura, cabelo ) {
this.idade = idade;
this.cor = cor;
this.altura = altura;
this.cabelo = cabelo;
this.setInfo = (function( idade, cor, altura, cabelo ) {
this.idade = idade;
this.cor = cor;
this.altura = altura;
this.cabelo = cabelo;
})
});
this.getInfo = (function() {
return ( this.idade + " " + this.cor + " " + this.altura + " " + this.cabelo );
});
});
Mulheres.prototype.descrever = (function() {
return ( "A mulher tem a idade: " + this.idade + " a cor: " + this.cor +
" altura: " + this.altura + " com os cabelos: " + this.cabelo );
});
var Suzana = new Mulheres();
Suzana.setInfo( "21", "branca", "1.74", "loira" );
console.log( Suzana.getInfo() );
var Carol = new Mulheres( "22", "Morena", "1,65", "Cabelos Escuros" );
console.log( Carol.descrever() );
Exemplo 5:
// Criamos a Classe
var Classe = (function() {
})
Classe.prototype.nascer = (function() {
})
Classe.prototype.morrer = (function() {
})
Classe.prototype.respirar = (function() {
})
var Mulheres = (function( nome ) {
this.nome = nome
});
Mulheres.prototype = new Classe(); // definimos que Mulher vai usar a Classe ou Modelo emulada como um protótipo
Mulheres.prototype.constructor = Mulheres(); // Alterando o construtor do objeto usado como protótipo
Mulheres.prototype.programar = (function() { // método programar apenas para Mulheres
return ( "A : " + this.nome + " é doida." );
});
var Programadora = new Mulheres( "Tânia" ); // Setando o valor de nome
console.log( Programadora.programar() ) // usando o método definido em Mulheres
console.log( Programadora.nome );
Exemplo 6:
var MaquinadoTempo = (function() {
var destino = "5 de Outubro, 1955";
this.getDestino = (function() {
return ( destino );
});
});
var delorean = new MaquinadoTempo();
console.log( delorean.getDestino() );
Exemplo 7:
// Isolando o construtor
function Carro() {
this.roncar = function() {
console.log( "vrumm vrumm" );
}
}
var meuCarro1 = new Carro();
var meuCarro2 = new Carro();
console.log( meuCarro1.constructor );
console.log( meuCarro2.constructor );
Exemplo 8:
function Carro() {}
Carro.prototype.roncar = function() {
console.log( "Vruumm Vrumm");
}
var meuCarro1 = new Carro();
var meuCarro2 = new Carro();
meuCarro1.roncar();
meuCarro2.roncar();
Exemplo 9:
// Usando a criação de Objetos literais
var veiculo = veiculo || {};
veiculo.dirigir = (function () {
console.log( "vrooom..." );
});
// Usando o Object.create
var carro = Object.create( veiculo );
carro.roncar = (function() {
console.log( "vroom vroom" );
});
var meuCarro = Object.create( carro );
meuCarro.roncar();
meuCarro.dirigir();
Exemplo 10:
/*
* Isso poderia ser uma Implementação do Decorator.
* Sim, é um outro Pattern.
* Em breve vamos entrar mais em detalhes..
* Criamos o Construtor Veiculo:
*/
var Veiculo = (function( tipoVeiculo ){
this.tipoVeiculo = tipoVeiculo || "carro";
this.modelo = "comum";
this.licenca = "00000-000";
})
var testeInstancia = new Veiculo( "carro" );
console.log( testeInstancia );
// Saída:
// Veiculo: carro, modelo: comum, licença: 00000-000
// Vamos criar uma nova instancia do Veículo, para ser decorada...
var caminhao = new Veiculo( "caminhao" );
// Adicionando novas funcionalidades ao Veículo
caminhao.setModelo = (function( modeloNome ){
this.modelo = modeloNome;
});
caminhao.setCor = (function( cor ){
this.cor = cor;
});
// Testando o valor dos setters e observando se o valor está correto
caminhao.setModelo( "Ferrari" );
caminhao.setCor( "Vermelho" );
console.log( caminhao );
// Saída:
// Veiculo: caminhao, modelo: Ferrari, cor: Vermelho
// Demonstrando que o "Veiculo" ainda está inalterado
var segundaInstancia = new Veiculo( "carro" );
console.log( segundaInstancia );
Exemplo 11:
/*
* Fazendo outra Implementação do Decorator
* Baseado na implementação de um dos nossos mestres
* Só utilizando o que aprendemos aqui no TutsMais
*/
var Carro = (function() {
this.custo = (function() { return 6000; });
this.custoamais = (function() { return 1000; });
});
// Decorator 1 - Adicionamos uma Peça ao valor do Carro.
var Som = (function( carro ) {
// Decoramos o custo do Carro que vem do Construtor de cima.
var c = carro.custo();
carro.custo = (function() {
// Retornamos a o Custo e adicionamos o valor do Som.
return c + 100;
})
});
// Decorator 2 - Variamos o tipo da função, mas o ideal é que
// seja sempre: Todas as Funções do tipo: Anônimas ou Todas do tipo definido.
function LuzDianteira( carro ){
var c = carro.custo();
carro.custo = (function(){
return c + 200;
});
}
// Decorator 3
function Farol( carro ){
var c = carro.custo();
carro.custo = (function(){
return c + 250;
});
}
// Substituição do carro nos parâmetros, por preco.
var preco = new Carro();
Som( preco );
LuzDianteira( preco );
Farol( preco );
console.log( preco.custo() ); // Retorna 6550
console.log( preco.custoamais() ); // Retorna 1000
var total = preco.custo() + preco.custoamais();
console.log( total ); // Retorna 7550
Exemplo 12: (Bônus usando Canvas)
// Primeiro crie a tag do canvas como no exemplo:
// <canvas id="canvas" width="150" height="150">Seu browser não suporta Canvas...</canvas>
/*
* JavaScript Html5 Canvas
* Copyright (C) 2012 - Rodrigo Nery
*
* Esse triângulo é free; Você pode redistribuir ou modificar
* Sobre os termos da GNU General Public License
*
* License is available at http://www.gnu.org/licenses/gpl.html
*/
// Meu NameSpace, evitando qualquer conflito e deixando mais bonito!
var NS = NS || {};
// Criando minha Classe com o NameSpace
NS.Class = (function() {
// Meu Construtor pegando o id Canvas e o Contexto
var Canvas = (function() {
this.canvas = document.getElementById("canvas");
this.ctx = canvas.getContext("2d");
});
// Crio meu Triangulo e herdo o construtor
Canvas.prototype.triangulo = (function() {
// Desnecessário porém é boa prática verificar o contexto
if( this.ctx ) {
// Cor do Triângulo em HSL ou Hue Saturation and Lightness
this.ctx.fillStyle = "hsl( 353, 100%, 72% )";
// Começo o Path
this.ctx.beginPath();
// O ponto de partida do desenho são as coordenadas 35,50
this.ctx.moveTo( 35,50 );
this.ctx.lineTo( 150,100 );
this.ctx.lineTo( 150,15 );
this.ctx.fill();
}
});
// Retorno o Objeto pra ser usado fora da Classe
return new Canvas();
// Auto Executo a Classe on Dom Load..
}( NS.Class ));
// Invoco o Objeto Triângulo com HTML5 ;D
NS.Class.triangulo();
Exemplo 13: (Bônus usando Canvas MicroTemplate)
/*
* JavaScript Html5 Canvas
* Copyright (C) 2012 - Rodrigo Nery
*
* Esse MicroTemplate é free; Você pode redistribuir ou modificar
* Sobre os termos da GNU General Public License
*
* License is available at http://www.gnu.org/licenses/gpl.html
*/
// Criando o NameSpace que verifica se já existe e se não existir, cria.
var Tag = Tag || {};
Tag.Class = (function() {
var Template = (function() {
this.elemento = document.createElement( 'canvas' );
this.ID = document.getElementById( 'canvas' );
})
// Criando a Tag Canvas...
Template.prototype.criarTag = (function() {
this.elemento.id = 'canvas';
this.elemento.className = 'canvas';
this.elemento.setAttribute( 'width', '540px' );
this.elemento.setAttribute( 'height', '540px' );
this.elemento.innerHTML = 'Seu Browser não suporta a tag Canvas.';
this.ID.appendChild( this.elemento );
})
return new Template();
}( Tag.Class ));
// Iniciando a Tag
Tag.Class.criarTag();
Considerações Finais
Bom, por hoje é só… Tente absorver o máximo dos conceitos que foram vistos!
Espero que todas às suas dúvidas sobre essa parte de Orientação a Objetos e herança sejam solucionadas depois desse post.
Na próxima semana, vou falar sobre Objetos literais, entre outros…
Espero você lá!
Acho q o site esta com algum problema de codifica
Já foi arrumado ;D