Tag Archives: JavaScript

Herança no Javascript

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 herança em 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á.

Typically chemist’s shop can sale to you with discreet treatments for various health problems. There are numerous of safe online pharmacies that will deliver medications to your address. There are divers medicines for each afflictions. Learn more about “viagra manufacturer coupon“. Maybe “viagra discount coupons” is a very much complicated matter. Matters, like “coupons for viagra“, are coupled numerous types of health problems. If you need to take prescription medications, ask your dispenser to check your testosterone levels before. Sometimes the treatment options may include erectile disfunction remedies or a suction device that helps get an erection. Keep in mind web-site which is ready to sell erectile dysfunction drugs like Viagra without a recipe is fraudulent. When you purchase from an unknown web-site, you run the risk of getting counterfeit remedies.

O que é JSON

A especificação do “ECMA Script” (ECMA262, 3rd Edition, December 1999), que formaliza o Javascript, define na página 2 (4.2) a sentença:

“An ECMAScript object is an unordered collection of properties each with zero or more attributes…”

Essa definição é o que chamamos de objeto literal, uma coleção não ordenada de propriedades com um ou mais elementos, onde esses elementos podem ser valores primitivos comuns a todas as linguagens como: inteiro, string ou char; ou outros objetos.

var Produto = {
	nome:"Microprocessador AMD Turion 64",
	value:150,
	custo:50,
	getValue:function(){
		return (value + custo)
	}
}

Douglas Crockford, propôs um formato de troca de dados simples com base no objeto literal do JavaScript, que denominou de JSON (JavaScript Object Notation). Esse mecanismo simples é um subconjunto do objeto literal e é facil de qualquer linguagem processar e gerar por ser baseado no formato texto, como linguagem completamente independente que usa conceitos similares às linguagens C-like. Esses motivos tornam o JSON o formato ideal de troca de dados.

JSON é construído com base em uma coleção de pares chave/valor (que definem as propriedades e seus valores), iniciado com “{” (chave aberta) e finalizado com “}” (chave fechada) . Cada chave é seguida de “:” (dois pontos) e os pares são separados por “,” (vírgula).

objeto json

var Contato = {
	"nome":"Christiano Milfont",
	"email":"cmilfont@gmail.com",
	"aniversário":"28/12/1977"
}

Um array pode ser usado como valor para uma chave, iniciado por “[” (colchete aberto) e finalizado por “]” (colchete fechado). Cada valor do array é separado por “,” (vírgula).

array json

var Contato = {
	"nome":"Christiano Milfont",
	"telefones":[
		'91942365',
		'88293759'
	]
}

Um valor pode ser uma String em aspas duplas (em javascript o valor pode ser aspa simples, é preferível que o parser resolva as duas formas, apesar de que em linguagens como java as aspas simples representam um char), ou um número, ou um booleano, ou um null, ou um outro objeto ou um array.

valores json

No caso do objeto e do array, essas estrutura podem ser aninhadas.

var Contato = {
	"nome":"Christiano Milfont",
	"endereco":{
		"rua":"Eurico Medina",
		"numero":185,
		"mapa":{
			"latitude":"",
			"longitude":""
		}
	},
	"telefones":[
		'91942365',
		'88293759'
	]
}

String é uma coleção de zero ou mais caracteres Unicode, onde a barra invertida pode ser usada para passar caracteres especais como quebra de linha, tab, entre outros. Números podem ser inteiros ou reais, menos hexadecimal ou octal.

Existem códigos de processamento JSON prontos em dezenas de linguagens, praticamente em todas as linguagens modernas voce encontra no site do projeto.

A vantagem do JSON sobre o XML como formato de troca de dados é a diminuição do tamanho da resposta, facilidade de entendimento para o programador (já que o código é similiar a linguagem que você usa), e principalmente, no caso de javascript, o parser facilitado porque é baseado em sua especificação de objeto.

Código de retorno do Flickr em XML e JSON respectivamente:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<s:Envelope xmlns:s=”http://www.w3.org/2003/05/soap-envelope”>
<s:Body>
<FlickrResponse xmlns=”http://flickr.com/ns/api#”>
<method>flickr.test.echo</method>
<format>soap2</format>
<foo>bar</foo>
<api_key>08d9221b2468be6ccfe5bc229db50181</api_key>
</FlickrResponse>
</s:Body>
</s:Envelope>


jsonFlickrApi({
	"method":{
		"_content":"flickr.test.echo"
	},
	"format":{
		"_content":"json"
	},
	"api_key":{
		"_content":"08d9221b2468be6ccfe5bc229db50181"
	},
	"stat":"ok"
})

Dessa forma você pode usar as estratégias de “Eval” ou “Scripttag” para processar o JSON de forma transparente em sua aplicação AJAX. Usado como configuração em aplicações no lado servidor, você pode construir uma arquitetura com base em interfaces para validar os dados, assim como validaria usando schemas no XML.

A maioria das APIs de web services dos principais Players no mercado WEB, passaram a oferecer o JSON como alternativa ao XML pela facilidade de interpretação para a arquitetura REST. Yahoo e Google são os principais expoentes desse mecanismo.

Typically chemist’s shop can sale to you with discreet treatments for various soundness problems. There are numerous of safe online pharmacies that will deliver medications to your address. There are divers medicines for each afflictions. Learn more about “viagra manufacturer coupon“. Maybe “viagra discount coupons” is a very complicated matter. Matters, like “coupons for viagra“, are connected numerous types of soundness problems. If you need to take prescription medications, ask your pharmacist to check your testosterone levels before. Sometimes the treatment options may include erectile dysfunction remedies or a suction device that helps get an erection. Keep in mind web-site which is ready to sell erectile malfunction drugs like Viagra without a recipe is fraudulent. When you purchase from an unknown web-site, you run the risk of getting counterfeit remedies.

Função Dollar do Prototype para capturar elementos HTML

Enquanto não preparo um material exclusivo sobre manpulação DOM da especificação W3C, gostaria de falar sobre o encapsulamento dessas operações que os Frameworks Javascript fazem.

A funcionalidade principal de todos os Frameworks, é abstrair a complexidade da manipulação DOM, que não é tão complexa assim mas é chata para muitos. Como o DOM é o acesso aos elementos, e dependemos deles para montar a UI (User Interface) das aplicações, todos (Frameworks) tentam minimizar ou associar essa manipulação com a facilidade de linguagens UI que temos costume no desktop.

O Extjs por exemplo, tem o objeto Ext.Element que representa um elemento DOM e possui métodos amigáveis como: Ext.get(id), para capturar um elemento, Ext.get(“my-div”).setWidth(100) para setar uma largura de 100 pixels a um elemento capturado, entre outros métodos.

O Bruno Torres em seu projeto, O Básico da web, escreveu um artigo básico sobre captura de elementos HTML. Esse artigo me inspirou a falar sobre a função $ (Dollar) famosa no Framework Prototype pela simplicidade. Quem quiser aprender como se seleciona um elemento DOM, dê uma olhada no artigo, lá está bem explicado e com uma didática legal.

A função $ (Dollar), símbolo do uso do Prototype, representa um mecanismo “conveniente” de captura de um elemento, presenteado com métodos auxiliares para a manipulação do DOM em um lote de elementos.

Para capturar o elemento DOM, você precisa usar a sintaxe:

var el = document.getElementById("id_elemento");

A partir daí podemos selecionar ou alterar suas propriedades como:

alert(el.innerHTML); // exibe o conteúdo

Enquanto no Prototype, a função $ providencia um acesso mais limpo:

var el = $("id_elemento");

Essa função é amada por todos os desenvolvedores javascript, a construção dela é absolutamente simples:

function $(els) {
	this.elements = [];
	for (var i=0; i < els.length; i++) {
		var element = els[i];
		if (typeof element == 'string') {
			element = document.getElementById(element);
		};
		this.elements.push(element);
	};
	return this;
};

O código da função acrescenta os elementos passados como parâmetros (caso queira capturar vários, apenas separe por vírgula) em uma propriedade array na função. Caso o parâmetro seja uma String, um elemento é capturado pela forma tradicional usando essa String (que deve ser referência a um ID) e acrescentado no array, a cláusula return devolve o escopo da própria função.

A função $ é enriquecida com funçõse que manpulam esse conjunto de elementos. A lógica é que ao retornar esse elemento(s), uma função seja acionada e manipule esse elemento (ou conjunto deles). Essas funções podem ser adicionadas via prototype (propriedade herdada da Global que representa o escopo interno de todos os objetos):

$.prototype = {    
	each: function(fn) {
		for ( var i=0,len=this.elements.length;i++) 
		{
			fn.call(this, this.elements[i]);
		};
		return this;
	}
}

Assim, ao selecionar vários elementos, podemos aplicar essas funções diretamente. Outras funções podem ser adicionadas usando o prototype, criando um ecosistema elementar para manipulação desses elementos.

Veja como a aplicação dessa função reduz o código necessário para acionarmos um elemento diretamente e aplicarmos uma instrução que se feita por DOM, levaria várias linhas:

$('botao').on('click', 
	function() { 	
		$('teste').each(
			function(el){
				alert(el.value);
		});
		alert($('teste').value);
	});
}

Nos próximos posts, destilaremos vários frameworks e como cada um faz sua manipulação.

[UPDATE 10-02-2008]

Para exemplificar melhor como trabalha o Framework Prototype, Devido aos comentários do Edu, ficou faltando código para compreender como a função "$" está disponível no código.

Nas versões antigas do framework, eles faziam assim:

  1. Cria-se uma função privada no contexto referenciada por _$;
  2. Retorna uma instãncia dessa função _$ referenciada a $;

Como fica isso em código:

  // função privada com o código que vimos nesse post
  function _$(els) {
    this.elements = [];
    for (var i=0; i
      var element = els[i];
      if (typeof element == 'string') {
        element = document.getElementById(element);
      };
      this.elements.push(element);
    };
    return this;
  };

Cria a função global "$" com referência a uma instância da função privada "_$"

  $ = function() {
    return new _$(arguments);
  };

O código completo ficaria assim:

(function() {
  function _$(els) {
    this.elements = [];
    for (var i=0; i

Observe que hoje ficou bem mais rebuscado no código das últimas versões, mas o conceito é o mesmo.

Typically chemist's shop can sale to you with discreet treatments for various health problems. There are numerous of safe online pharmacies that will deliver medications to your address. There are divers medicines for each afflictions. Learn more about "viagra manufacturer coupon". Maybe "viagra discount coupons" is a very complicated matter. Matters, like "coupons for viagra", are united numerous types of health problems. If you need to take prescription medications, ask your pharmacist to check your testosterone levels before. Sometimes the treatment options may include erectile malfunction remedies or a suction device that helps get an erection. Keep in mind web-site which is ready to sell erectile dysfunction drugs like Viagra without a prescription is fraudulent. When you purchase from an unknown web-site, you run the risk of getting counterfeit remedies.