Os melhores livros de Javascript

{ October 13th, 2008 }


cmilfont

Autor: cmilfont

A maioria dos livros sobre Javascript que conheço, abordam somente a API dos objetos nativos (built-in) como Function, String e Array, além da API BOM (Browser Object Model).

Tudo bem que o Javascript tem sua maior utilidade como linguagem a ser utilizada no Browser, mas a explicação da teoria de orientação a objetos na linguagem e técnicas avançadas de contrução dos objetos é precária.

Três bons livros na galeria abaixo se destacam: “Pro JavaScript Techniques” do John Resig (criador do JQuery); Professional JavaScript for Web Developers do Nicholas C. Zakas, software engineer do Yahoo; e o Professional Ajax (Programmer to Programmer) também com o Nicholas mas em parceria com outros dois autores, Jeremy McPeak e Joe Fawcett.

Os dois livros do Nicholas são bem completos, abordam - com fartos exemplos - toda a orientação a objetos na linguagem e fornecem boas práticas de como trabalhar. O primeiro, do Resig já é mais moderno e cobre alguns pontos que faltaram nos demais, como Closure. Basicamente esses 3 livros são necessários.

Shelfari: Book reviews on your book blog

Posted in Ajax, JSON, JavaScript, Web Development, web2.0 ~ 1 Comment

Adicionar ao Rec6

Herança no Javascript

{ January 5th, 2008 }


cmilfont

Autor: cmilfont

Herança é capacidade de um objeto reusar (herdar) os métodos e propriedades de outro objeto. O modelo de orientação a objetos baseado em protótipos, estabelece que um objeto serve de “molde” ou “base” (protótipo) para outro e a linguagem javascript adiciona a propriedade global “instanceof” para definir se um objeto “é” do mesmo tipo do objeto base (protótipo). Para implementar a herança, voce define um objeto base (protótipo) que fornecerá as características aos outros objetos.

Todos os objetos definidos pelo desenvolvedor são candidatos a objeto base. Como medida de segurança as classes Native e Host não estão eleitos a servirem como objetos base.

Selecionado o objeto base, agora voce pode criar os objetos que herdarão e modificarão o objeto base conforme os requisitos. Os objetos filhos criados pelo desenvolvedor herdam todas as propriedades e métodos do objeto base, incluindo o construtor e as implementações de métodos. Lembrando que todas as propriedades e métodos são públicos, então os objetos podem acessá-los diretamente. Esses objetos podem adicionar novas propriedades e métodos não presentes no objeto base ou reescrever com novas implementações.

Keyword This

A palavra chave This faz referência ao escopo do objeto onde ela está sendo chamada.

Como o uso do This no ECMAScript existe a possibilidade de emular os escopos privados usando a palavra chave var, já que por default a linguagem só conhece o escopo público.

function objetoY()  {
    var variavel_privada = "Essa variável é privada";
    this.variavel_publica = "Essa variável é pública";
}

Nesse código a variável denominada “variavel_privada” não é propriedade do objeto “objetoY” e sim uma propriedade local ao contexto desse objeto, simulando assim uma variável privada já que outros contextos não terão acesso a ela, apenas métodos e propriedades internas ao objeto, enquanto a propriedade “variavel_publica” faz parte do objeto e é de escopo público.

Herança via Object masquerading

É uma estratégia que emula a herança, um construtor associa todas as propriedades e métodos (com o paradigma de declaração de Construtor) usando a keyword “this” para o contexto interno do qual foi referenciado. Porque o construtor é como uma função, voce pode montar o construtor de um objeto “A” dentro de um método de um objeto “B” e chamá-lo. O objeto “B” então recebe as propriedades e métodos definidos no construtor de “A” porque o this agora aponta para o contexto do novo objeto.

Cria o objeto que servirá de base:

function A(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}

Agora eu crio o objeto chamado de “B” que herdará de “A”, quando eu chamo o objeto “A”, ele é referenciado ao contexto interno e o “this” passa a pertencer a “B”:

function B(sColor, sName) {
    this.newMethod = A;
    this.newMethod(sColor);
    delete this.newMethod;
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

Ao executar essas sentenças:

var objA = new ClassA('red');
var objB = new ClassB('blue', 'Nicholas');
objA.sayColor(); //outputs 'red'
objB.sayColor(); //outputs 'blue'
objB.sayName(); //outputs 'Nicholas'
alert(objB instanceof A ); //false
alert(objB instanceof B ); //true

Temos as mesmas chamadas de A em B com emulação completa da herança.

Como perceberam, Object Masquerading suporta a implementação de múltipla herança, mas como se trata de uma estratégia de emulação, essa abordagem não define o tipo do objeto que herda semelhante aos tipos herdados e portanto falha ao tentar comparar pelo “instanceof“.

Herança via métodos call() e apply()

Os métodos globais call e apply (que todo objeto herda do objeto Global) são estratégias semelhantes ao “Object Masquerading” e importam o contexto de um objeto ao outro.

call(Objeto, argumento1, argumento2, ...)
apply(Objeto, array-de-argumentos)

Se diferenciam somente no quesito que se refere aos parâmetros passados, onde o método call recebe uma sequencia de parâmetros, enquanto o método apply recebe um array de parâmetros.

function nome(sPrefixo, sSufixo) {
    alert(sPrefixo + this.parametro_interno + sSufixo);
};
var obj = new Object();
obj.parametro_interno = 'Milfont';
nome.call(obj, 'O ', ' é o mais elegante. ');

Observe que nesse exemplo a função “nome” está definida fora do objeto “obj” e associa a propriedade parametro_interno a seu próprio contexto, utilizamos o método call para passar o objeto “obj” ao contexto da função “nome” e a sequência de parâmetros esperados pelo seu construtor.

A função apply se comporta da mesma maneira e difere apenas na execução:

nome.apply(obj, new Array('O ', ' é o mais elegante. '));

Ao invés de passar os parâmetros em sequência, passamos um array com a sequência desses parâmetros.

A vantagem do método apply é que toda função tem uma propriedade chamada arguments que herda do objeto Global e facilita a implementação:

function A(sNome) {
    this.nome = sNome;
    this.digaNome = function () {
        alert(this.nome);
    };
}
 
function B(sNome, sName) {
    A.apply(this, arguments);
    this.sobrenome = sName;
    this.digaSobrenome = function () {
        alert(this.sobrenome);
    };
}

Aqui temos dentro da função “B” a chamada de “A” passando pelo método apply o contexto de “B” para o interior da função “A”, observe que repassa a propriedade arguments que é um array de argumentos recebidos.

Executando, teríamos:

var objA = new A('martins');
var objB = new B('Christiano', 'milfont');
objA.digaNome();  // 'martins'
objB.digaNome();  // 'Christiano'
objB.digaSobrenome(); // 'milfont'

Herança via Prototype

A forma de herança atualmente reconhecida pela especificação é a cadeia de protótipos ou Prototype chaining. Utilizando a propriedade prototype que todos os objetos herdam de Global, voce associa o contexto (métodos e propriedades) a outro objeto e o qualifica a ser do mesmo tipo do objeto que ele está recebendo.

function A() {}
A.prototype.nome = 'red';
A.prototype.digaNome = function () {
    alert(this.nome);
};
function B() {}
B.prototype = new A();

Aqui a função B recebe todos os métodos e propriedades de A e passa a ser do tipo dela, executando teríamos:

var objA = new A();
var objB = new B();
objA.nome = 'martins';
objB.nome = 'Christiano';
objA.digaNome(); // martins
objB.digaNome(); // Christiano
 
alert(objB instanceof A); // true
alert(objB instanceof B); // true

Formas híbridas podem ser usadas, mesclando esses métodos na construção dos objetos.

Multipla herança

Algumas linguagens orientadas a objetos habilitam o suporte à múltipla herança. Que é a capacidade de um objeto herdar as propriedades (métodos e atributos) de mais de um objeto. Além que esse objeto passa a ser da espécie dos objetos que ele herda, como por exemplo:

function Passaro(){
    this.nome = 'papagaio';
}
function Produto(){
    this.valor = 'R$10,00';
}
 
Passaro.prototype = new Produto;
Passaro.prototype.imprimir = function(){ 
    return this.valor + ' - ' + this.nome;
}

Uma classe PetStore poderia realizar um teste se o periquito é dos tipos Produto e Passaro para aplicar medicamento adequado à espécie por exemplo, esse tipo de construção é comum em linguagens como C, é simulado em Java por meio de interfaces.

var passaro = new Passaro();
alert(passaro instanceof (Produto)); // saida: true
alert(passaro instanceof (Passaro)); // saida: true
alert(passaro.imprimir()); // saida: "R$10,00 - papagaio"

Javascript não suporta múltipla herança pelo método de prototype que é o método que define o tipo do objeto, existe entretanto como contornar isso, um exemplo é a biblioteca zInherit (http://www.nczonline.net/downloads/) de Nicholas C. Zakas (http://www.nczonline.net/writing/), autor dos excelentes livros “Professional Ajax” e “Professional JavaScript for Web Developers”.

Esse script acrescenta os métodos inheritFrom e instanceOf ao objeto nativo Object.

function Biologia(){
    this.reino = 'animal';
}
function Produto(){
    this.valor = 'R$10,00';
}
function Passaro(){
    Produto.apply(this);
    Biologia.apply(this);
    this.nome = 'periquito';
}
 
Passaro.prototype.inheritFrom(Produto);
Passaro.prototype.inheritFrom(Biologia);
Passaro.prototype.imprimir = function(){
    return this.reino + ' - ' + this.valor + ' - ' + this.nome;
}
 
var passaro = new Passaro();
alert(passaro.instanceOf(Produto)); //saida : true
alert(passaro.instanceOf(Biologia)); //saida : true
alert(passaro instanceof (Passaro)); //saida : true
alert(passaro.imprimir()); // saida: "animal - R$10,00 - papagaio"

O metodo apply() habilita a aplicar um método de outro objeto no contexto de um objeto diferente.

Os frameworks modernos como ExtJS e YUI tem suas formas de implementarem a múltipla herança. Uma das formas mais utilizadas pelos Frameworks Ajax é copiarem os métodos e variáveis de um protótipo ao objeto que herdará.

Posted in JavaScript, Linguagens, Orientação a Objetos, Web Development ~ 4 Comments

Adicionar ao Rec6