JavaScript Orientado a Objetos – Parte 2

O JavaScript, apesar de ser usado há muito tempo quase que exclusivamente como linguagem de programação estruturada, também é uma linguagem de programação orientada a objetos poderosa. Nessa segunda parte da série, vamos nos aprofundar um pouco mais nessa técnica de programação.

A Propriedade prototype

No JavaScript, toda função construtora possui uma propriedade chamada Function.prototype. Essa propriedade nos permite adicionar e, em certos casos modificar, propriedades ou métodos de um construtor, após sua definição. Diferente de PHP, por exemplo, podemos adicionar propriedades durante a execução.

function Person() {}
        var me = new Person();
        alert(me.eyes); // undefined
        Person.prototype.eyes = 2;
        alert(me.eyes); // 2

Como se pode notar, na primeira tentativa não tínhamos a propriedade definida. Após isso, adicionada em tempo de execução, já temos a propriedade definida.

Também há certas exceções na utilidade do Function.prototype. A primeira delas é que essa propriedade não consegue sobrescrever qualquer coisa que já tenha sido definida no construtor. Não podemos definir uma propriedade no construtor e depois mudar seu valor através de Function.prototype.

function Person() { this.eyes = 2; }
        var me = new Person();
        alert(me.eyes); // 2
        Person.prototype.eyes = 1;
        alert(me.eyes); // 2, continuo tendo 2 olhos

Para resolver esse problema e continuar usando Function.prototype, podemos definir a propriedade fora do construtor usando a técnica, e sobrescrevê-la da mesma maneira.

function Person() {}
        Person.prototype.eyes = 2;
        var me = new Person();
        alert(me.eyes); // 2
        Person.prototype.eyes = 1;
        alert(me.eyes); // 1

Outro pequeno problema é quando definimos objetos ou arrays através dessa propriedade. Veja:

function Person() {}
        Person.prototype.uses = ["watch", "glasses"];
        var me = new Person();
        var you = new Person();
        me.uses.push("hat");
        alert(me.uses); // ["watch", "glasses", "hat"]
        alert(you.uses); // ["watch", "glasses", "hat"]

Com base no exemplo, pode-se ver que o array é compartilhado, assim como todos os seus itens. Moral da história: é preferível definir tudo no próprio construtor, ou então definir apenas métodos através de Function.prototype.

Encapsulamento

Formalmente, encapsulamento ainda não existe no JavaScript, mas podemos usar esse recurso disfarçado.

Tudo o que criamos dentro de nossos construtores está no escopo público, ou seja, pode ser acessado de dentro do construtor ou do restante do script. Uma maneira de simular variáveis privadas, que só podem ser acessadas de dentro do construtor e por seus métodos, é utilizando o escopo local. Lembra-se de quando falei sobre escopo de variáveis?

function Person() {
                this.public = "Variável Pública";
                var private = "Variável Privada";
                this.publicMethod = function() {
                        alert(this.public);
                        alert(private);
                }
                var privateMethod = function() {
                        alert(private);
                }
                this.callPrivate = function() {
                        alert(private);
                }
        }
        var me = new Person();
        alert(me.public); // "Variável Pública";
        alert(me.private); // undefined
        me.publicMethod();
        me.privateMethod(); // Retornará erro
        me.callPrivate();

O exemplo acima exemplifica bem de onde cada tipo de variável pode ser acessado. Já o uso de variáveis protegidas (protected) necessitam de mais gambiarras, mas isso fica pra outra vez.

Quanto ao uso de métodos privados só existe um pequeno problema: não é possível acessar propriedades ou métodos públicos diretamente. Para isso, é necessário modificar o escopo em que a função executada, através de Function.bind (função user-defined).

function Person() {
                this.public = "Variável Pública";
                var bindPublic = function() {
                        alert(this.public);
                }.bind(this);
                bindPublic();
        }
        var me = new Person();

Para testar, lembre-se de copiar a função Function.bind!

E a parte 2 se encerra aqui. Volto na parte 3 pra falar mais um pouco sobre programação orientada a objetos. Até lá!

Posts Relacionados

Postado em fevereiro 19, 2008 às 22:12

Comentários

Trackbacks

  1. As Vantagens de Prototype « JulioGreff Dezembro 09, 2006 @ 13:26
  2. Funções em Diferentes Escopos » JulioGreff Dezembro 23, 2007 @ 13:22

Deixe seu comentário