Objota O mundo orientado a objetos

Classes e Objetos em JavaScript

Posted on outubro 31, 2010

O objetivo deste artigo é apenas mostrar a curiosa forma que toma uma classe feita em javascript puro.

Muitos usuários da biblioteca prototype não fazem questão de fazer desta forma afinal, nem sempre é viável. Para quem não sabe prototype é uma biblioteca que maximiza o poder de orientação a objetos do javascript. Porém no nosso caso presente, não a utilizaremos.

Veremos algumas coisas básicas comparando uma classe em php, por exemplo, e a classe em javascript.

A primeira coisa que podemos ver é que o JS não possui um envoltório chamado class para isso ele usa function.

Php:

class MinhaClasse{
 	//Aqui o conteúdo
}

JavaScript:

function MinhaClasse(){
 	//Aqui o conteúdo
}

Ótimo, e o construtor da classe. Em php se utiliza um método com o mesmo nome da classe ou __constructe. E em JS..  não tem!! Isso mesmo. O conteúdo do construtor fica mergulhado juntamente com os atributos.

Php:

class MinhaClasse{
        private $nome;
 	public function MinhaClasse($novoNome){
 		$this->nome = $novoNome;
 	}
}

JavaScript:

function MinhaClasse(novoNome){
  	var nome;
        this.nome = novoNome;
}

Vejamos agora uma declaração  dos famosos métodos get e set:

Php:

class MinhaClasse{
        private $nome;
 	public function MinhaClasse($novoNome){
 		$this->nome = $novoNome;
 	}
        public function getNome(){
 		return  $this->nome ;
 	}
        public function setNome($novoNome){
 		$this->nome = $novoNome;
 	}
}

JavaScript:

function MinhaClasse(novoNome){
  	var nome;
        this.nome = novoNome;
        this.getNome=function(){
 		return this.nome;
 	};
        this.setNome=function(otroNome){
 		this.nome = otroNome;
 	};
}

Agora vamos ver uma peculiaridade do javascript de passar uma função via parâmetro, ou dados no formato JSON. Veja como é simples:

Função via parâmetro:

function hello(){
 	document.write("Oi objota!");
}
function executaPraMim(funcaoQualquer){
 	funcaoQualquer(); //pronto! Ele chama a função
}

//passo uma função já implementada ou..
executaPraMim(hello());

//implementa-se no ato da parametrização
executaPraMIm(function(){
 	document.write("Essa eu implementei agora!");
});

Muito bacana não é!

Agora vejamos um exemplo bem simples de uma função que recebe dados no formato JSON.


function mostra(dados){
	Alert("O nome é: "+dados.nome+"\nemail: "+dados.email);
}
//vejamos a chamada
Mostra({nome: "Objota", email: "objota@teste.com.br"});

Neste artigo vimos como implementar classes, receber funções via parâmetro e dados no formato JSON. Neste artigo quis mostrar algumas peculiaridades do JS, nada em especial. Somente algumas dicas aos curiosos. Abaixo temos os exemplos completos coloque os dois arquivos no mesmo diretório e inicie a índex.html.

É isso! Até a próxima. Dúvidas, postem aí! 😉

Classes.js


//Classe Carro
function Carro(){
    var placa;
    var cor;

    this.getPlaca=function(){
        return this.placa;
    };

    this.setPlaca=function(novaPlaca){
        this.placa = novaPlaca;
    };
    this.getCor=function(){
        return this.cor;
    };

    this.setCor=function(novaCor){
        this.cor = novaCor;
    };
}

//Classe Pessoa
function Pessoa() {

    //@interface
    var nome;
    var idade;
    var email;
    var carro;
    //@end

    //@constructe
    this.carro = new Carro();
    this.carro.setPlaca(7520);
    this.carro.setCor("Amarelo");
    //@end

    //@implementation
    this.getCarro=function(){
        return this.carro;
    };

    this.getNome=function(){
      return this.nome;
    };

    this.getIdade=function() {
      return this.idade;
    };

    this.getEmail=function() {
      return this.email;
    };

    this.setNome=function(_nome) {
      this.nome = _nome;
    };

    this.setIdade=function(_idade) {
      this.idade = _idade;
    };

    this.setEmail=function(_email) {
      this.email = _email;
    };

    this.mostraValores=function() {
      return 'Nome: '+this.nome+
             '<br/>Idade: '+this.idade+
             ' anos<br/>Email: '+this.email+
             '<br/>Carro:<br/>* Placa:'+this.carro.getPlaca()+
             '<br/>**Cor: '+this.carro.getCor();
    };

    //Recebe uma função por parâmetro e executa
    this.executa=function(i,funcao){
          if(i > 0)
          funcao();
    };

    //Recebe dados no formato JSON via parâmetro
    this.mostraJson=function(dados){
          return 'Id:'+dados.id_conteudo+'<br/>Nome: '+dados.nome;
    };
    //@end
}

index.html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Classes em javascript</title>
<script type="text/javascript" src="Classes.js"></script>
</head>

<body>
<script type="text/javascript">
  var Objota = new Pessoa();

  Objota.setNome('Objota - POO');
  Objota.setIdade(21);
  Objota.setEmail('email@objota.com.br');

  document.write(
    Objota.mostraValores()
  );
  document.write(
    Objota.getCarro().getPlaca()
  );

  //Altera placa do meu atributo carro, que é um objeto!
  Objota.getCarro().setPlaca(5051);

  //Passando função por parâmetro
  Objota.executa(1,function(){
      Objota.setNome('Rodrigo I.O.');
      Objota.setIdade(22);
      Objota.setEmail('bass_oliveira@hotmail.com');

      document.write(Objota.mostraValores());
  });

  //Passo dados no formato JSON via parâmetro {label: valor}
  document.write(Objota.mostraJson({id_conteudo: 50, nome: 'Manezinho'}));
</script>
</body>
</html>

Posted by Rodrigo Ireno

Comentários (14) Trackbacks (3)
  1. Pode explicar ou apontar lugares para eu saber mais sobre essa biblioteca prototype?

  2. Muito Bom foi util!

  3. Quando você cria a classe ‘Carro’ você declara ‘placa’ e ‘cor’ usando ‘var’, e ‘var’ é como uma declaração ‘private’, enquanto que ‘this’ é como uma declaração ‘public’, se tentar acessar em ‘Carro’ o ‘alert(new Carro().getPlaca());’ você até consegue, mas você consegue acessar também a variável que deveria ser privada de nome ‘placa’ pois você usou o ‘this’ dentro do método getPlaca() quando não deveria ter usado nada. Isso foi intencional?

    []’s

    • Você está certo Adrian, eu não havia notado isso.
      de fato eu uso um set antes.. o que na verdade cria o atributo em tempo de execução.. então teoricamente não estou usando as variaveis com ‘var’.
      Foi um descuido meu isso. Não cheiguei a reparar.

      Obrigado por reparar neste detalhe, mas de qualquer forma fica a apresentação do conceito de uso de objetos em javascript.

      []’s

  4. O certo não seria

    executaPraMim(hello);

    Ao invés de

    executaPraMim(hello());

    ???

  5. O certo não seria

    executaPraMim(hello);

    Ao invés de

    executaPraMim(hello());

    ??

  6. Artigo bastante simples e muito esclarecedor. Eu que sou neófito em js e estou estudando este assunto foi uma boa ajuda inclusive o comentário do Adrian. Porém eu penso que a biblioteca (framework) prototypejs e a propriedade prototype que usamos para indicar que uma propriedade da classe é herdável não são a mesma coisa.

  7. De Excelência,me ajudou muito, obrigado meu caro !!!

  8. Eu utilizo esta classe para ser usada por todo o site

    function prodEscolhido() {
    var produto;

    this.pegaProduto = function () {
    return produto;
    };

    this.setaProduto = function (valor) {
    produto = valor;
    };
    }

    mas quando o browser muda de página, a classe tem seu valor perdido.

    Como contornar isso?

  9. Alguem pode me dizer como passar como os valores o json para outras funçoes???

    $(window).load(function () {

    var maxVal,
    valoresG = [],
    etiquetasX = [],
    etiquetasY = [];

    var cv, ctx;

    function obterValores()
    {
    // Valores
    $(“#data tr td:nth-child(2)”).each(function () {
    valoresG.push($(this).text());
    });

    //Etiquetas
    $(“#data tr td:nth-child(1)”).each(function () {
    etiquetasX.push($(this).text());
    });
    }

    function initCanvas()
    {

    cv = $(“#canvas”).get(0);
    if (!cv)
    {
    return;
    }

    ctx = cv.getContext(‘2d’);
    if (!ctx)
    {
    return;
    }
    }

    function valorMaximo(arr)
    {
    maxVal = 0;

    for (i = 0; i < arr.length; i++)
    {
    if (maxVal < parseInt(arr[i]))
    {
    maxVal = parseInt(arr[i]);
    }
    }

    maxVal *= 1.1;
    }

    function escalar(param)
    {
    return Math.round((param / maxVal) * alturaG);
    }

    function x(param)
    {
    return (param * larguraB) + ((param + 1) * espacoB) + offsetX;
    }

    function y(param)
    {
    return alturaG – escalar(param);
    }

    function ancho()
    {
    return larguraB;
    }

    function altura(param)
    {
    return escalar(param);
    }

    function desenharEtiquetasX()
    {
    ctx.save();
    ctx.font = "10px 'arial'";
    ctx.fillStyle = "#000";
    for (index = 0; index < valoresG.length; index++)
    {
    ctx.fillText(etiquetasX[index], x(index), alturaG + 17);
    }
    ctx.restore();
    }

    function desenharEtiquetasY()
    {
    ctx.save();
    for (index = 0; index < this.nEtiquetasY; index++)
    {
    etiquetasY.push(Math.round(maxVal / nEtiquetasY * (index + 1)));
    ctx.fillStyle = "#000";
    ctx.fillText(etiquetasY[index], offsetX, y(etiquetasY[index]) + 10);
    }
    ctx.fillText("0", offsetX, alturaG + 7);
    ctx.restore();
    }

    function desenharGraficoBarras()
    {
    for (index = 0; index < valoresG.length; index++)
    {
    ctx.save();
    ctx.fillStyle = "#B7B7B7";
    ctx.fillRect(x(index), y(valoresG[index]), ancho(), altura(valoresG[index]));
    ctx.restore();
    }
    $("#data").hide();
    }

    obterValores();
    initCanvas();
    valorMaximo(valoresG);
    desenharEtiquetasX();

    desenharGraficoBarras({
    espacoB: 45,
    larguraB: 45,
    alturaC: 220,
    nEtiquetasY: 8,
    offsetX : 20,
    larguraG :550,
    alturaG:200});

    });


Leave a comment