Modification des objets ECMAScript
- Page précédente Définir une classe ou un objet
- Page suivante Exemple d'inheritance mechanism
En utilisant ECMAScript, non seulement on peut créer des objets, mais aussi modifier le comportement des objets existants.
L'attribut prototype peut non seulement définir les propriétés et méthodes du constructeur, mais aussi ajouter des propriétés et méthodes aux objets locaux.
Créer de nouvelles méthodes
Créer de nouvelles méthodes à partir des méthodes existantes
On peut utiliser l'attribut prototype pour définir de nouvelles méthodes pour n'importe quelle classe existante, comme on le ferait pour sa propre classe. Par exemple, se souvenez-vous de la méthode toString() de la classe Number ? Si on lui passe un paramètre 16, elle affiche une chaîne en hexadécimal. Si le paramètre de cette méthode est 2, alors elle affiche une chaîne en binaire. Nous pouvons créer une méthode qui convertit directement un objet nombre en chaîne hexadécimale. Créer cette méthode est très simple :
Number.prototype.toHexString = function() { return this.toString(16); };
Dans cet environnement, le mot-clé this pointe vers une instance de Number, donc on peut accéder à toutes les méthodes de Number. Avec ce code, on peut réaliser l'opération suivante :
var iNum = 15; alert(iNum.toHexString()); // Affiche "F"
Comme le nombre 15 équivaut à F en hexadécimal, le message d'alerte affichera "F".
Renommer les méthodes existantes
Nous pouvons également renommer les méthodes existantes pour qu'elles soient plus compréhensibles. Par exemple, nous pouvons ajouter deux méthodes enqueue() et dequeue() à la classe Array, qui ne font que répéter les appels aux méthodes push() et shift() existantes :
Array.prototype.enqueue = function(vItem) { this.push(vItem); }; Array.prototype.dequeue = function() { return this.shift(); };
Ajouter des méthodes sans rapport avec les méthodes existantes
Bien sûr, on peut ajouter des méthodes qui n'ont rien à voir avec les méthodes existantes. Par exemple, supposons que nous devions déterminer la position d'un élément dans un tableau, sans méthode locale pour faire cette tâche. Nous pouvons facilement créer la méthode suivante :
Array.prototype.indexOf = function (vItem) { for (var i=0; i<this.length; i++) { if (vItem == this[i]) { return i; } } return -1; }
Cette méthode indexOf() est identique à la méthode de la classe String du même nom, elle recherche chaque élément dans le tableau jusqu'à ce qu'elle trouve un élément correspondant à celui passé en paramètre. Si elle trouve un élément correspondant, elle renvoie la position de cet élément, sinon, elle renvoie -1. Avec cette définition, nous pouvons écrire le code suivant :
var aColors = new Array("red","green","blue"); alert(aColors.indexOf("green")); // Affiche "1"
Ajouter une nouvelle méthode à un objet local
Enfin, pour ajouter une nouvelle méthode à chaque objet local ECMAScript, il faut la définir sur la propriété prototype de l'objet Object. Comme nous l'avons expliqué dans les chapitres précédents, tous les objets locaux héritent de l'objet Object, donc toute modification apportée à l'objet Object se reflète sur tous les objets locaux. Par exemple, si vous souhaitez ajouter une méthode pour afficher la valeur actuelle de l'objet en utilisant un avertissement, vous pouvez utiliser le code suivant :
Object.prototype.showValue = function () { alert(this.valueOf()); }; var str = "hello"; var iNum = 25; str.showValue(); // Affiche "hello" iNum.showValue(); // Affiche "25"
Ici, les objets String et Number héritent de la méthode showValue() de l'objet Object, et en appelant cette méthode sur leurs objets respectifs, on affiche "hello" et "25".
Redéfinir une méthode existante
Comme on peut définir de nouvelles méthodes pour des classes existantes, on peut également redéfinir des méthodes existantes. Comme décrit dans les chapitres précédents, le nom de la fonction est simplement un pointeur vers la fonction, donc il peut facilement pointer vers d'autres fonctions. Si vous modifiez une méthode locale, comme toString(), que se passe-t-il ?
Function.prototype.toString = function() { return "Function code hidden"; }
Le code précédent est parfaitement légal et le résultat de l'exécution correspond parfaitement aux attentes :
function sayHi() { alert("hi"); } alert(sayHi.toString()); // Affiche "Function code hidden"
Peut-être vous souvenez-vous, dans le chapitre sur l'objet Function, on a présenté que la méthode toString() de Function généralement affiche le code source de la fonction. En surchargeant cette méthode, on peut renvoyer une autre chaîne de caractères (dans cet exemple, on peut renvoyer "Function code hidden"). Mais, que devient la fonction originale pointée par toString() ? Elle sera recyclée par le programme de recyclage des unités de stockage inutilisées, car elle est complètement abandonnée. Il n'existe pas de méthode pour restaurer la fonction originale, donc il est plus sûr de stocker son pointeur avant de la surcharger, afin de pouvoir l'utiliser à l'avenir. Parfois, vous pouvez même appeler la méthode originale dans la nouvelle méthode :
Function.prototype.originalToString = Function.prototype.toString; Function.prototype.toString = function() { if (this.originalToString().length > 100) { return "Function too long to display."; } else { return this.originalToString(); } };
Dans ce code, la première ligne conserve une référence à la méthode toString() actuelle dans l'attribut originalToString. Ensuite, une méthode personnalisée remplace la méthode toString(). La nouvelle méthode vérifie si la longueur du code source de la fonction est supérieure à 100. Si c'est le cas, elle renvoie un message d'erreur indiquant que le code de la fonction est trop long, sinon elle appelle la méthode originalToString() et renvoie le code source de la fonction.
Liaison tardive (Very Late Binding)
Techniquement parlant, il n'existe pas de liaison tardive. Ce livre utilise ce terme pour décrire un phénomène dans ECMAScript, où il est possible de définir des méthodes d'un objet après son instanciation. Par exemple :
var o = new Object(); Object.prototype.sayHi = function () { alert("hi"); }; o.sayHi();
Dans la plupart des langages de programmation, les méthodes de l'objet doivent être définies avant l'instanciation de l'objet. Ici, la méthode sayHi() est ajoutée après la création d'une instance de la classe Object. Dans les langages traditionnels, non seulement on n'a jamais entendu parler de cette opération, mais on n'a jamais entendu parler de la méthode qui est automatiquement attribuée à l'instance de l'objet Object et qui peut être utilisée immédiatement (ligne suivante).
Attention :Il est déconseillé d'utiliser la méthode de liaison tardive, car elle est difficile à suivre et à enregistrer. Cependant, il est toujours utile de comprendre cette possibilité.
- Page précédente Définir une classe ou un objet
- Page suivante Exemple d'inheritance mechanism