Informatique


Les prototypes

Aller à

JS est orienté prototype

Le JS, contrairement aux autres langages de programmation, utilise pour construire les objets des prototypes.
Le prototype fournit des fonctions et des propriétés aux objets en plus des propriétés et méthodes déjà présents au niveau de l'objet lui-même.

Le grand avantage de cette organisation est que la modification du prototype profite à tous les objets créés avant cette modification!
Donc, si on ajoute une propriété ou une méthode au prototype d'un objet, cette propriété ou cette méthode sera utilisable par tous les objets construits sur ce prototype.


La propriété __proto__

Prenons un objet vide....

Démo
<h2>Créer un prototype vide avec une fonction constructeur</h2>
<script>
function Pvide(){
	
}
pv1=new Pvide();
console.log(pv1);
</script>

On constate:
au niveau de l'objet pv1: on a 1 propriété: __proto__, cette dernière à pour valeur Object. Cela veut dire que le prototype de Pvide est de type Object.

Si on développe cette propriété on remarque que celle-ci contient la méthode constructeur Pvide (c'est normal puisque tous les objets Pvide sont construit selon cette méthode) et une propriété __proto__ évaluée à Object.

Si on développe cette propriété on remarque que celle-ci contient la méthode constructeur Object (c'est normal puisque tous les objets sont construit selon cette méthode) et une série d'autres méthodes qui ont été ajoutées au prototype.

Le prototype dons la méthode constructeur est Object() est le dernier de la hiérarchie, en effet, ce prototype n'a pas de propriété __proto__.


Un autre exemple

Reprenons le constructeur Animal déjà utilisé précédemment:

Démo
<h2<Créons des objets de type Animal</h2<
<script>
// Constructeur Animal
function Animal(nom,sexe,age) {
// Initialisation des propriétés de l'objet
	this.nom=nom;
	this.sexe=sexe;
	this.age=age;		
	this.photo=this.nom+".jpg";
	
	this.affic=function(){
		var s= (this.sex==="F")? "Femelle":"Mâle";
		return "<div>"+s+" - "+this.nom+" - "+this.age+" ans"+" - "+this.photo+"</div>";
	}	
}
// Instanciation d'un objet à partir du constructeur
var monPinguin = new Animal("Costard","M","5");
console.log(monPinguin);
document.write(monPinguin.affic());
</script>

On constate:
au niveau de l'objet monPinguin: on a 1 méthode affic() et 5 propriétés: age, nom, photo, sexe, __proto__, cette dernière à pour valeur Object.

Si on développe cette propriété on remarque que celle-ci contient la méthode constructeur Animal (c'est normal puisque tous les objets Animal sont construit selon cette méthode) et une propriété __proto__ qui représente le prototype sur lequel est construit le prototype Animal.

Si on développe cette propriété on remarque que celle-ci contient la méthode constructeur Object (c'est normal puisque tous les objets sont construit selon cette méthode) et une série d'autres méthodes qui ont été ajoutées au prototype.


L'héritage des prototypes

Exemple: un objet qui utilise une méthode héritée du prototype Object

Démo
<h2<Créons des objets de type Animal</h2<
<script>
// Constructeur Animal
function Animal(nom,sexe,age) {
// Initialisation des propriétés de l'objet
	this.nom=nom;
	this.sexe=sexe;
	this.age=age;		
	this.photo=this.nom+".jpg";
	
	this.affic=function(){
		var s= (this.sex==="F")? "Femelle":"Mâle";
		return "<div>"+s+" - "+this.nom+" - "+this.age+" ans"+" - "+this.photo+"</div>";
	}	
}
// Instanciation d'un objet à partir du constructeur
var monPinguin = new Animal("Costard","M","5");
console.log(monPinguin.valueOf());
</script>

On constate:

  • Le navigateur tente de déterminer si l'objet monPinguin implémente une méthode valueOf()
  • Aucune n'est présente, le navigateur vérifie donc si le prototype objet de monPinguin (Animal) contient cette méthode
  • Pas de valueOf() non plus, donc le navigateur regarde si le prototype objet du constructeur Animal() possède cette méthode. Il y en a une, donc il l'appelle et tout va bien !

On ne peut pas ajouter des propriétés et des méthodes "à la volée" comme pour les objets littéraux.
Si on veut ajouter des propriétés et/ou des méthodes il est obligatoire d'utiliser la propriété prototype de l'objet.

Ajouter une méthode au prototype

On peut ajouter des méthodes au sein du prototype de l'objet, pour ce faire on utilise la propriété prototype du type Animal.

Démo
<h2<Créons des objets de type Animal</h2<
<script>
// Constructeur Animal
function Animal(nom,sexe,age) {
// Initialisation des propriétés de l'objet
	this.nom=nom;
	this.sexe=sexe;
	this.age=age;		
	this.photo=this.nom+".jpg";
	
	this.affic=function(){
		var s= (this.sex==="F")? "Femelle":"Mâle";
		return "<div>"+s+" - "+this.nom+" - "+this.age+" ans"+" - "+this.photo+"</div>";
	}	
}
// Instanciation d'un objet à partir du constructeur
var monPinguin = new Animal("Costard","M","5");
Animal.prototype.afficNomMaj=function(){
	document.write(this.nom.toUpperCase());
}
monPinguin.afficNomMaj();
console.log(monPinguin);
</script>

On constate dans la console que la méthode afficNomMaj a bien été rajoutée au prototype de l'objet monPinguin, dorénavant tous les objets de type Animal auront accès à cette méthode.


La chaîne des prototypes

Voici un script qui renvoie la chaîne de prototypes héritée par un objet.

Démo
<head>
 <meta charset="utf-8">
<script src="ofonc_6.js"></script>
</head>
<body>
<h2>Créer un prototype vide</h2>
<script>
function herit(monobj){
	var proto=Object.getPrototypeOf(monobj);
	
	var heritage=[];
	
	while(proto !== null){
		
		heritage[heritage.length]=proto.constructor.name;
		
		proto=Object.getPrototypeOf(proto);
	}
	return heritage;
}
var monPinguin = new Animal("Costard","M","5");
var stich = new Chien("Stich","M","6");
document.write(stich.affic());
console.log(herit(monPinguin));
console.log(herit(stich));
console.log(herit(document));
var div=document.getElementsByTagName("div")[0];
console.log(herit(div));
</script>
</body>

L'mage en prime...

On constate:

  • getPrototypeOf() est une méthode implémentée dans le prototype Object
  • constructor est une propriété de chaque type d'objet
  • name est une propriété de la propriété constructor