Este artigo necessita de uma revisão técnica.

Este artigo necessita de uma revisão editorial.

Esta tradução está incompleta. Ajude atraduzir este artigo.

JavaScript tem fortes capacidades de programação orientada a objetos, apesar de ocorrerem algumas discussões devido às diferenças da orientação a objetos no JavaScript em comparação com outras linguagens.

Esse artigo começa com uma introdução à programação orientada a objetos, em seguida, revisa o modelo de objetos em JavaScript e, por fim, demonstra conceitos de programação orientada a objetos no JavaScript.

Revisão do Javascript

Se você não se sente confiante com conceitos de JavaScript como variáveis, tipos, funções e escopo, você pode ler sobre estes tópicos em Uma reintrodução ao JavaScript. Você também pode consultar o Core JavaScript 1.5 Guide.

Programação Orientada a Objetos

Programação Orientada a Objetos é um paradigma de programação que usa abstração para criar modelos baseados no mundo real. POO usa várias técnicas vindas de paradigmas previamente estabelecidos, incluindo modularidade, polimorfismo e encapsulamento. Atualmente, muitas linguagens de programação populares (como Java, JavaScript, C #, C ++, Python, PHP, Ruby e Objective-C) permitem a programação orientada a objetos (POO).

A POO pode ser vista como o projeto de software utilizando uma coleção de objetos em cooperação, em oposição a uma vista tradicional, em que um programa pode ser visto como uma série de funções, ou simplesmente como uma lista de instruções para o computador. Em OOP, cada objeto é capaz de receber mensagens, processar dados e envio de mensagens para outros objetos. Cada objeto pode ser visto como uma pequena máquina independente, com um papel ou responsabilidade distinta.

A POO se destina a promover uma maior flexibilidade e facilidade de manutenção na aplicação, e é muito popular em engenharia de softwares de grande escala. Em virtude de sua forte ênfase na modularidade, código orientado a objetos destina-se a ser mais simples de desenvolver e mais fácil de entender mais tarde, prestando-se a uma análise mais direta, codificação e compreensão de situações e procedimentos mais complexos do que nos métodos de programação menos modulares.

Terminologia

Espaço de nomes
Um recipiente que permite empacotar todas as funcionalidades em um nome único e específico da aplicação.
Classe
Define as características do objeto. Uma classe é uma definição modelo das propriedades e métodos de um objeto.
Objeto
Um exemplar de uma classe.
Atributo
Uma característica do objeto, como cor, modelo, fabricante se estivemos representando um veículo, por exemplo.
Método
Uma ação do objeto, como ligar, desligar, frear se estivemos representando um veículo, por exemplo. É uma subrotina ou função associada a uma classe.
Construtor
Um método chamado assim que um novo exemplar do objeto for criado. Ele geralmente tem o mesmo nome da classe que o contém.
Herança
Uma classe pode herdar características de outra classe.
Encapsulamento
Uma maneira de agrupar os dados e os métodos que usam os dados.
Abstração
A conjunção de herança complexa, métodos, propriedades de um objeto devem refletir adequadamente um modelo da realidade.
Polimorfismo
Diferentes classes podem definir o mesmo método ou propriedade.

Para uma descrição mais extensiva sobre programação orientada a objetos, veja Orientação a objetos na Wikipédia.

Programação Baseada em Protótipos

Programação baseada em protótipos é um estilo de programação orientada a objetos na qual não temos presença de classes. Em vez disso, a reutilização de comportamento (equivalent à herança das linguagens baseadas em classes) é realizada através de um processo de decorar (ou expandir) objetos existentes que servem como protótipos. Este modelo também é conhecido como sem classes, orientado a protótipo, ou programação baseada em exemplares.

O exemplo original (e o mais canônico ) de uma linguagem baseada em protótipo é a linguagem de programação Self desenvolvida por David Ungar e Randall Smith.  No entanto, o estilo de programação sem classes tem se tornado mais popular recentemente, e foi adotado por linguagens de programação como JavaScript, Cecil, NewtonScript, lo, MOO, REBOL, Kevo, Squeak (quando se utiliza o framework Viewer para manipular componentes do Morphic) e várias outras.

Programação Orientada a Objetos em Javascript

 

Espaço de nomes

Um espaço de nomes é um recipiente que permite aos desenvolvedores agrupar funcionalidades em um único nome específico para uma aplicação. Em JavaScript, um espaço de nomes é simplesmente outro objeto contendo métodos, propriedades e objetos.

Nota: É importante notar que, em Javascript, não existe diferença a nível da linguagem entre objetos normais e espaços de nomes. Isso é diferente do que ocorre em muitas outras linguagens orientadas a objetos, e pode ser causa de confusão entre programadores(as) JavaScript novatos(as).

A ideia por trás de criar um espaço de nomes em JavaScript é simples: cria-se um objeto global e todas as variáveis, métodos e chamadas de função tornam-se propriedades daquele objeto. O uso de espaços de nomes também reduz a chance de conflitos de nomes em uma aplicação, já que os objetos de cada aplicação são propriedades de um objeto global definido pela aplicação.

Vamos criar um objeto global chamado MEUAPP:

// espaco de nomes global
var MEUAPP = MEUAPP || {};

No código acima, primeiro verificamos se MEUAPP já está definido (no mesmo arquivo ou em outro). Se estiver, usamos o objeto MEUAPP global existente. Caso contrário, criamos um objeto vazio chamado MEUAPP, que encapsula métodos, variáveis e objetos

Podemos também criar sub-espaços de nomes.

// sub espaço de nomes
MEUAPP.eventos = {};

A seguir, temos a sintaxe para criar um espaço de nomes e adicionar variáveis, funções e um método:

// Criando um recipiente chamado MEUAPP.metodosEmComum
// para métodos e propriedades em comum

MEUAPP.metodosEmComum = {

  regexParaNome: "", // definindo uma expressao regular
                     // para validação de nomes

  regexParaTelefone: "",  // define uma expressao regular para
                          //validacao de numeros de telefone

// Objeto junto a declaracoes de método

MEUAPP.eventos = {

    adicionarTratador: function(elemento, tipo, funcao) {

    // codigos

    },

    removerTratador: function(elemento, tipo, funcao) {

    // codigos

    },

    obterEvento: function(e) {

    // codigos

    }

    // é possível adicionar outros métodos e propriedades

}

// Sintaxe para usar o método adicionarTratador:

MEUAPP.eventos.adicionarTratador("youre1", "tipo", tratador);

Objetos inclusos por padrão

 

JavaScript tem vários objetos incluídos em seu núcleo; por exemplo, objetos como Math, Object, Array, e String. O exemplo abaixo mostra como usar o objeto Math para obter um número aleatório usando seu método random().

console.log(alert(Math.random()));
Nota: Este e todos os exemplos a seguir presumem que uma função console.log() está definida globalmente. A função console.log() não faz parte do JavaScript em si, mas muitos navegadores a implementam para ajudar no processo de depuração.

Veja Core JavaScript 1.5 Reference:Global Objects para a lista dos objetos inclusos por padrão em JavaScript.

Cada objeto em JavaScript é um exemplar do objeto Object e, portanto, herda todas as suas propriedades e métodos.

Objetos Personalizados

A Classe

JavaScript é uma linguagem baseada em protótipos e não contém a declaração class, como vemos em C++ ou Java. Isso, às vezes, causa confusão em programadores(as) acostumados(as) a linguagens com uma declaração para classes. Em vez disto, JavaScript usa funções como classes. Definir uma classe-função é tão fácil quanto definir uma função. No exemplo abaixo, nós definimos uma nova classe chamada Pessoa.

 

O objeto (exemplar de uma classe)

Para criar um novo exemplar de um objeto obj, usamos a declaração new obj, atribuindo o resultado (que é do tipo obj) a uma variável que será acessada depois.

No exemplo acima, definimos uma classe chamada Pessoa. No exemplo abaixo, criamos dois exemplares (pessoa1 e pessoa2).

var person1 = new Person();
var person2 = new Person();
Nota: Por favor, veja também Object.create para um novo e alternativo método que cria um exemplar não-inicializado.

O Construtor

O construtor é chamado no momento que o exemplar do objeto é criado. O construtor é um método da classe. Em JavaScript, a função serve como o construtor do objeto. Portanto, não há a necessidade de definir explicitamente um método construtor. Toda ação declarada na classe é executada no momento da criação.

O construtor é usado para definir as propriedades do objeto ou para chamar metodos que preparem o objeto para o uso. O acréscimo de métodos e suas definições à classe funciona através do uso uma sintaxe diferente, descrita mais adiante, nesse artigo.

No exemplo abaixo, o construtor da classe Pessoa envia uma mensagem ao log quando um exemplar de Pessoa é criado.

var Pessoa = function () {
  console.log("exemplar criado");
}

var pessoa1 = new Pessoa();
var pessoa2 = new Pessoa();

Propriedades (atributos de objetos)

Propriedades são variáveis contidas em uma classe; cada exemplar do objeto tem essas propriedades. Propriedades devem ser definidas no construtor (ou função) da classe, de modo que sejam criados em cada exemplar.

A palavra-chave this, que se refere ao objeto atual, te permite trabalhar com propriedades do lado de dentro da classe. Acessos (leitura ou escrita) uma propriedade do lado de fora da classe são feitos com a sintaxe NomeDoExemplar.Propriedade, assim como em C++, Java e várias outras linguagens. (Dentro da classe, a sintaxe this.Propriedade é usada para obter ou atribuir um valor ao objeto.)

 

var Pessoa = function(nome) {
  this.nome = nome;
  console.log('Exemplar de Pessoa criado');
};

var pessoa1 = new Person('Alice');
var pessoa2 = new Person('Bob');

// mostrando as propriedades nome dos objetos
console.log('pessoa1 é ' + pessoa1.nome); // envia "pessoa1 é Alice" ao log
console.log('pessoa2 é ' + pessoa2.nome); // envia "pessoa2 é Bob" ao log

Métodos

Métodos são funções (e definidos como funções), mas seguem a mesma lógica das propriedades. Chamar um método é parecido com acessar uma propriedade, mas você coloca () no final do nome do método, possivelmente com argumentos. Para definir um método, atribua uma função a uma propriedade com nome do prototype da classe. Depois disso, você pode chamar o método do objeto usando o mesmo nome ao qual você atribuiu a função.

No exemplo abaixo, definimos e usarmos o método dizerOla() na classe Pessoa .

var Pessoa = function (nome) {
  this.gender = gender;
  alert('Person instantiated');
}

Person.prototype.sayHello = function()
{
  alert ('hello');
};

var person1 = new Person('Male');
var person2 = new Person('Female');

// call the Person sayHello method.
person1.sayHello(); // hello

In JavaScript methods are regular function objects that are bound to a class/object as a property which means they can be invoked "out of the context". Consider the following example code:

function Person(gender) {
  this.gender = gender;
}

Person.prototype.sayGender = function()
{
  alert(this.gender);
};

var person1 = new Person('Male');
var genderTeller = person1.sayGender;

person1.sayGender(); // alerts 'Male'
genderTeller(); // alerts undefined
alert(genderTeller === person1.sayGender); // alerts true
alert(genderTeller === Person.prototype.sayGender); // alerts true

This example demonstrates many concepts at once. It shows that there are no "per-object methods" in JavaScript since all references to the method point to the exact same function, the one we have defined in the first place on the prototype. JavaScript "binds" the current "object context" to the special "this" variable when a function is invoked as a method(or property to be exact) of an object. This is equal to calling the function object's "call" method as follows:

genderTeller.call(person1); //alerts 'Male'
Veja mais sobre em Function.call e Function.apply

Herança

Inheritance is a way to create a class as a specialized version of one or more classes (JavaScript only supports single class inheritance). The specialized class is commonly called the child, and the other class is commonly called the parent. In JavaScript you do this by assigning an instance of the parent class to the child class, and then specializing it. In modern browsers you can also use Object.create to implement inheritance.

JavaScript does not detect the child class prototype.constructor see Core JavaScript 1.5 Reference:Global Objects:Object:prototype property, so we must state that manually.

No exemplo abaixo, nós definimos a classe Student como filha da classe Pesson. Então redefinimos o método sayHello() e cria o método sayGoodBye().

// define a classe Person
function Person() {}

Person.prototype.walk = function(){
  alert ('I am walking!');
};
Person.prototype.sayHello = function(){
  alert ('hello');
};

// define a classe  Student 
function Student() {
  // Call the parent constructor
  Person.call(this);
}

// herda de Person
Student.prototype = new Person();

// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
 
// replace the sayHello method
Student.prototype.sayHello = function(){
  alert('hi, I am a student');
}

// adiciona o método sayGoodBye 
Student.prototype.sayGoodBye = function(){
  alert('goodBye');
}

var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();

// check inheritance
alert(student1 instanceof Person); // true 
alert(student1 instanceof Student); // true

Using Object.create the inheritance line would instead be:

Student.prototype = Object.create(Person.prototype);

Encapsulamento

In the previous example, Student does not need to know how the Person class's walk() method is implemented, but still can use that method; the Student class doesn't need to explicitly define that method unless we want to change it. This is called encapsulation, by which every class inherits the methods of its parent and only needs to define things it wishes to change.

Abstração

Abstraction is a mechanism that permits modeling the current part of the working problem. This can be achieved by inheritance (specialization), or composition. JavaScript achieves specialization by inheritance, and composition by letting instances of classes be the values of attributes of other objects.

The JavaScript Function class inherits from the Object class (this demonstrates specialization of the model). and the Function.prototype property is an instance of Object (this demonstrates composition)

var foo = function(){};
alert( 'foo is a Function: ' + (foo instanceof Function) );
alert( 'foo.prototype is an Object: ' + (foo.prototype instanceof Object) );

Polimorfismo

Just like all methods and properties are defined inside the prototype property, different classes can define methods with the same name; methods are scoped to the class in which they're defined. This is only true when the two classes do not hold a parent-child relation (when one does not inherit from the other in a chain of inheritance).

Notas

As técnicas apresentadas nesse artigo para implementar programação orientada objetos em JavaScript não são as únicas que podem ser usadas.

As ténicas utilizadas nesse artigo não usam nenhum tipo de hacks, nem tenta implantar teorias de outras linguagens em JavaScript. 

Existem outras ténicas que fazem um uso ainda mais avançado de programação orientada a  objetos em JavaScript, mas estão além desse artigo introdutório.

Referências

  1. Mozilla. "Core JavaScript 1.5 Guide", https://developer.mozilla.org/docs/Web/JavaScript/Guide
  2. Wikipedia. "Object-oriented programming", http://en.wikipedia.org/wiki/Object-...ed_programming

Original Document Information

  • Author(s): Fernando Trasviña <f_trasvina at hotmail dot com>
  • Copyright Information: © 1998-2005 by individual mozilla.org contributors; content available under a Creative Commons license

Es: https://developer.mozilla.org/es/docs/Introducción_a_JavaScript_orientado_a_objetos 

Etiquetas do documento e colaboradores

Última atualização por: GabrielLidenor,