Uma abordagem suave aos objectos em JavaScript

Nota introdutória: este texto foi escrito para um público alvo muito específico, sendo o objectivo principal o de introduzir o paradigma OO em JavaScript. Muita da beleza do paradigma e até da própria linguagem serão eventualmente matéria de desenvolvimento mais adiante.

A Programação Orientada a Objectos (do inglês Object-Oriented Programming – OOP) é um paradigma relativamente recente, introduzido no início dos anos 60.

Na génese deste paradigma está a noção do universo compostos por objectos que interagem entre si. Como o software visa resolver problemas do “mundo real”, a programação por objectos pretende simplificar a representação da realidade onde os objectos têm características (propriedades) e acções (métodos) que são capazes de realizar.

Se tomarmos como exemplo um carro, diríamos que o mesmo pode ser caracterizado da seguinte forma:

  • Propriedades: marca, modelo, cor, peso, …
  • Métodos: andar, parar, buzinar, …

O paradigma OO (Object-Oriented) surgiu como alternativa ao famoso paradigma imperativo e até funcional, sendo que algumas linguagens mais ou menos recentes suportam os dois.

A linguagem JavaScript (JS) que surgiu em 1995 dos laboratórios da Netscape, é um exemplo duma linguagem multi-paradigma, implementando o imperativo e orientado a objectos. Inicialmente foi implementada como parte integrante dos browsers, permitindo correr código do lado do cliente capaz de interagir com o utilizador, modificar as páginas e até de comunicar assincronamente.
É importante esclarecer que JavaScript nada tem que ver com a linguagem Java!

Voltando aos objectos e a sua implementação em JavaScript, podemos dizer que tudo na linguagem são objectos: mesmo uma string ou número inteiro têm as suas próprias propriedades e métodos.
Existe ainda um objecto especial designado Object, o qual não tem qualquer propriedade ou método.

var string = "ola mundo";
 
// o comprimento é uma propriedade das strings
string.length
 
// a conversão para maiúsculas é um método das strings
string.toUpperCase()
 
// o tal objecto especial
var my_object = new Object();
 
// alternativamente ainda podemos criar este objecto especial da seguinte forma
// mais adiante iremos explorar esta notação
var my_object2 = {};

Do exemplo acima:

  • .” (ponto) permite aceder às propriedades e métodos dum objecto;
  • new permite criar novos objectos.

Como seria de esperar a linguagem permite-nos criar os nosso próprios objectos.
Retomando o exemplo do carro:

// Declaração dum novo tipo de objecto
// Sempre que se quiser criar um novo carro será preciso indicar a marca, modelo, cor e peso
function Carro(marca,modelo,cor,peso)
{
    // cria as características do objecto carro conforme a informação que for dada
    this.marca = marca;
    this.modelo = modelo;
    this.cor = cor;
    this.peso = peso;
}
 
// Confere ao objecto "Carro" a capacidade de realizar a acção "andar"
Carro.prototype.andar = function()
{
    alert("vrrrrrr....");
}
 
// Confere ao objecto "Carro" a capacidade de realizar a acção "parar"
Carro.prototype.parar = function()
{
    alert("stop!");
}
 
// Confere ao objecto "Carro" a capacidade de realizar a acção "buzinar"
Carro.prototype.buzinar = function()
{
    alert('pi pi!');
}

Quando quisermos criar um novo carro:

// Criar o meu primeiro carro
var Fiat = new Carro("Fiat","Uno","preto",600);
 
// Pedir ao Fiat para andar
Fiat.andar();
 
// Pedir ao Fiat para buzinar
Fiat.buzinar();
 
// e que tal buzinar novamente?
Fiat.buzinar();
 
// e agora, parar!
Fiat.parar();

Quando compramos um carro ele não tem matricula, portanto é necessário que se possa adicionar uma:

// confere ao objecto Carro a capacidade de se atribuir uma matricula
Carro.prototype.adicionarMatricula = function(matricula)
{
    this.matricula = matricula;
}

Agora se criarmos um novo carro

var Peugeot = new Carro("Peugeot","106","cinza",900);
 
// vamos atribuir uma matricula ao carro
Peugeot.adicionarMatricula("00-00-AA");
 
// qual é a matricula do carro?
Peugeot.matricula;
 
// e que tal buzinar?
Peugeot.buzinar();

Edit  
2013-03-21: Uma excelente referência (en): Understanding JavaScript OOP — Sorella’s Basement