Modificação de Objetos ECMAScript
- Página anterior Definir classe ou objeto
- Próxima página Exemplo de mecanismo de herança
Usando ECMAScript, não só é possível criar objetos, mas também modificar o comportamento dos objetos existentes.
A propriedade 'prototype' pode não só definir atributos e métodos do construtor, mas também adicionar atributos e métodos ao objeto local.
Criar novos métodos
Criar novos métodos através de métodos existentes
Pode-se usar a propriedade prototype para definir novos métodos para qualquer classe existente, como se estivesse lidando com sua própria classe. Por exemplo, lembra-se do método toString() da classe Number? Se passar o parâmetro 16, ele será output como uma string hexadecimal. Se o parâmetro do método for 2, ele será output como uma string binária. Podemos criar um método que converte diretamente um objeto número em uma string hexadecimal. Criar esse método é muito simples:
Number.prototype.toHexString = function() { return this.toString(16); };
Neste ambiente, a palavra-chave this aponta para uma instância de Number, portanto, pode acessar todos os métodos de Number. Com esse código, podemos realizar a seguinte operação:
var iNum = 15; alert(iNum.toHexString()); //Saída "F"
Como o número 15 é F em hexadecimal, o aviso será exibido como "F".
Renomear métodos existentes
Também podemos renomear métodos existentes para nomes mais compreensíveis. Por exemplo, podemos adicionar dois métodos enqueue() e dequeue() à classe Array, que chamam repetidamente os métodos push() e shift() existentes:
Array.prototype.enqueue = function(vItem) { this.push(vItem); }; Array.prototype.dequeue = function() { return this.shift(); };
Adicionar métodos não relacionados aos existentes
Claro, também podemos adicionar métodos que não sejam relacionados aos métodos existentes. Por exemplo, suponha que você precise determinar a posição de um item em um array, não há método local que faça isso. Podemos facilmente criar o seguinte método:
Array.prototype.indexOf = function (vItem) { for (var i=0; i<this.length; i++) { if (vItem == this[i]) { return i; } } return -1; }
Este método indexOf() mantém a consistência com o método同名方法 da classe String, pesquisando cada item do array até encontrar o item que foi passado. Se encontrar o item correspondente, retorna a posição do item, caso contrário, retorna -1. Com essa definição, podemos escrever o seguinte código:
var aColors = new Array("red","green","blue"); alert(aColors.indexOf("green")); // Saída: "1"
Adicionar novos métodos para objetos locais
Por fim, se você quiser adicionar um novo método a todos os objetos locais do ECMAScript, você deve defini-lo na propriedade prototype do objeto Object. Como mencionado nos capítulos anteriores, todos os objetos locais herdam o objeto Object, então qualquer mudança feita no objeto Object será refletida em todos os objetos locais. Por exemplo, se você quiser adicionar um método que imprime o valor atual do objeto usando um alerta, você pode usar o seguinte código:
Object.prototype.showValue = function () { alert(this.valueOf()); }; var str = "hello"; var iNum = 25; str.showValue(); // Saída: "hello" iNum.showValue(); // Saída: "25"
Aqui, os objetos String e Number herdam o método showValue() do objeto Object, chamando esse método em seus próprios objetos, mostrando "hello" e "25".
Redefinir métodos existentes
Da mesma forma que você pode definir novos métodos para classes existentes, você também pode redefinir métodos existentes. Como mencionado nos capítulos anteriores, o nome da função é apenas um ponteiro para a função, portanto, pode ser facilmente apontado para outra função. O que acontece se você modificar um método local, como toString()?
Function.prototype.toString = function() { return "Function code hidden"; }
O código anterior é completamente válido e o resultado da execução é completamente conforme esperado:
function sayHi() { alert("hi"); } alert(sayHi.toString()); // Saída: "Function code hidden"
Talvez você ainda se lembre, no capítulo sobre o objeto Function, foi introduzido o método toString() do Function, que geralmente retorna o código-fonte da função. Sobrescrevendo esse método, você pode retornar outra string (neste exemplo, pode retornar "Function code hidden"). No entanto, o que acontece com a função original para a qual toString() aponta? Ela será recolhida pelo programa de recolha de unidades de armazenamento inúteis, pois foi completamente abandonada. Não há maneira de restaurar a função original, então é mais seguro armazenar seu ponteiro antes de sobrescrever o método original, para que ele possa ser usado no futuro. Às vezes, você até pode chamar o método original no novo método:
Function.prototype.originalToString = Function.prototype.toString; Function.prototype.toString = function() { if (this.originalToString().length > 100) { return "A função é muito longa para ser exibida."; } else { return this.originalToString(); } };
Neste código, a primeira linha armazena a referência ao método toString() atual na propriedade originalToString. Em seguida, um método personalizado substitui o método toString(). O novo método verifica se o comprimento do código-fonte da função é maior que 100. Se for, retorna uma mensagem de erro indicando que o código da função é muito longo, caso contrário, chama o método originalToString() e retorna o código-fonte da função.
Ligação muito tardia (Very Late Binding)
Técnicamente, não existe a ligação muito tardia. Este livro usa o termo para descrever um fenômeno no ECMAScript, que permite definir métodos após a instânciação do objeto. Por exemplo:
var o = new Object(); Object.prototype.sayHi = function () { alert("hi"); }; o.sayHi();
Em muitos linguagens de programação, é necessário definir os métodos do objeto antes da instânciação do objeto. Aqui, o método sayHi() é adicionado após a criação de uma instância da classe Object. Em linguagens tradicionais, não se conhece essa operação nem o método que automaticamente atribui ao objeto da instância de Object e pode ser usado imediatamente (na próxima linha).
Atenção:Não é recomendável usar o método de ligação muito tardia, pois é difícil rastrear e registrar. No entanto, ainda deve-se estar ciente dessa possibilidade.
- Página anterior Definir classe ou objeto
- Próxima página Exemplo de mecanismo de herança