la poo en javascript par un exemple pratique et visuel

avant propos

Fréquemment quand on parle de poo on se retrouve avec la même explication une voiture de couleur x de marque x...etc et si c'est pas une voiture c'est un animale ou autre et pour changer un peut j'ai fait ce tuto qui expliquera les concepts de base de la poo d'une façon différente de ce que l'on voit généralement avec toujours l'objectif de savoir a quoi peut servir réellement la poo dans une page web.

il existe deux principaux paradigme de poo celui utilisant les class et celui utilisant les prototype et Javascript utilise la poo par prototype mais il est tout a fait possible de faire de la poo par class plus precisement en utilisant la syntaxe des class impléménté dans javascript mais il faut avoir en tete que la mécanique en fond utilise toujours la poo par prototype. Le tuto ce concentrera principalement sur la poo par prototype.

Débuter en poo

La base

Pour bien comprendre l'utilité que peut avoir la poo nous allons créé un diaporama instanciable.

Vous pouvez voir le résultat sur cette page diaporama en poo

Nous allons partir sur la base d' un diaporama normale qui affichera une image toutes les x secondes en boucle.

<html>
<head>
<script type="text/javascript">
var tbdiapo=new Array ('d1.jpg','d2.jpg','d3.jpg','d10.jpg','d11.jpg','d12.jpg');
var tbindex=0;
var repertoir_image='images/';
function Diaporama(){
tbmage++;
document.getElementById('diapo_1').src=repertoir_image+tbdiapo[tbmage];
if(tbmage==tbdiapo.length-1){
tbmage=-1;
}
setTimeout(diap, 500 );
}
</script>
</head>
<body >
<img id="diapo_1" />
</body>
</html>

Un diaporama des plus simple il y a un tableau qui contient le nom des images, une variable global qui s'incrémente pour afficher chaque image contenu dans le tableau et une autre variable qui contient le nom du répertoire ou se situ les images, Dans la fonction il y a la modification de l'image et une condition qui reinitialise la variable d'incrémentation en fonction du tableau afin que le diapo tourne en boucle et enfin on a un setTimeout réglé a 1/2 seconde correspondant a la durée d'affichage d'une image.

pourquoi faire de la poo ?

Imaginons que l'on ai besoin de plusieurs diaporama on devra crée autant de script que de diaporama et il faudra donner un nom différent pour chaque fonction et variable afin d'éviter les scopes de nom En somme un vrais casse tête.
. Ou encore on pourrait créé une super fonction qui gèrerais plusieurs diaporama avec toute la logique nécessaire a ce niveau je conseille la vitamine C. De plus dans ce genre de fonction le fait de devoir gérer plusieurs chose passe par des condition des boucles et le tout tend a diminuer les performances.

un constructeur c'est quoi

un constructeur en javascript n'est autre qu'une fonction qui possèdera des attributs et des méthode

les attributs sont des variable elles peuvent donc contenir des chaine de caractère, des valeur numérique, des référence a un élément des array...etc. Quand aux méthodes aux il s'agit de fonction qui exécuteront donc du code.

en simplifiant:

attribut = variable
méthodes=fonction.

un constructeur est copié en mémoire autant de fois qu'on le désire en utilisant new pour chaque copie on dit que l'on cree une instance, chaque instances est un objet . Chaque objet est indépendante.

de quelle attributs avons nous besoin ?

Un constructeur est générique dans le sens ou il a toujours la même fonction pour toutes les instances et pour fonctionner il a besoin d'un certain nombre d'attribut. Il faut donc ce posé la question "de quelle attributs avons nous besoin ?" ou plus simplement de quelle éléments avons nous besoin pour faire fonctionner notre diaporama ?

Dans le cas du diaporama nous avons besoin des attributs suivant

- un lien vers la balise img associé au diaporama
- le tableau qui contient le nom des image
- le nom du répertoire ou se trouve les images
- la variable d’incrémentation
- la durée d'attente entre chaque transitions

créons notre constructeur

function Diaporama( cible,tableau,repertoire,duree){
this.Image=document.getElementById(cible);
this.Tableau=tableau;
this.temp=duree;
this.repertoir_image=repertoire;
this.tbmage=-1;
this.diap();
}

Dans le code hormis l'attribut 'this.tbmage' qui est la variable d'incrémentation on constate que chaque attributs correspondent aux paramètres de la fonction, paramètres qui seront transmis lors de l'instanciation que l'on verra plus bas.

on remarque la présence de this.diap() qui permettra d'appeler la fonction qui contiendra le diaporama au moment de l'instanciation afin de démarrer le diaporama automatiquement, bien evidement le lancement du diaporama est executé apres l'initialisation des attribut.

le diaporama

A ce stade il nous manque la fonction diaporama qui est ce que l'on appel une méthode de notre constructeur et qui sera la même que celle utilise dans la fonction basic a la seul différence qu l'on remplacera les paramètres par les attributs de l'objet.

Et la nous avons deux solutions.

Soit on créé la fonction a l'intérieur du constructeur

function Diaporama( cible, tableau,repertoire,duree){
this.cible=document.getElementById(cible);
this.Tableau=tableau;
this.temp=duree;
this.repertoir_image=repertoire;
this.tbmage=-1;
this.diap();
this.diap = function(){
this.tbmage++;
this.cible.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
if(this.tbmage==this.Tableau.length-1){
this.tbmage=-1
}
var that=this;
setTimeout(that.diap, that.temp);
}

Soit on utilise le prototype de notre constructeur.

prototype

un prototype est un conteneur de méthodes et propriété qui est rattaché par défaut au constructeur et chaque objets instancié avec ce constructeur partages sont prototype.

les méthodes et propriété du prototype sont définit en précisant le constructeur et en lui affublant soit une fonction anonyme soit un attribut.

ce qui donne pour un attribut:

Diaporama.prototype.une_propriete = "une_propriete"

pour une methode:

Diaporama.prototype.une_methode = function(){

du code...du code...

}

Le fait d'utiliser un prototype permet un gain de place en mémoire car contrairement a la fonction mis dans l'objet et qui pour chaque instance est copié en mémoire le prototype n'est copié en mémoire qu'une seul fois.

une deuxième différence est que si on modifie une des méthodes (fonctions) ou propriétés (variables) se trouvant dans le prototype le prototype étant partagé par les objets ils seront impacté par cette modification alors que dans le cas précédent il faudra accéder a tous les objet et ce un par un et faire la modification souhaité. d’où l'utilité du prototype.

un prototype c'est un peut comme un patron en couture on prend modèle sur lui et si on le modifie tous les modèles seront modifié a la différence près que même ceux précédemment crée bénéficieront de la modification.

function Diaporama( cible,tableau,repertoire,duree){
this.cible=document.getElementById(cible);
this.Tableau=tableau;
this.temp=duree;
this.repertoir_image=repertoire;
this.tbmage=-1;
this.diap();
}
Diaporama.prototype.diap = function(){
this.tbmage++;
this.cible.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
if(this.tbmage==this.Tableau.length-1){
this.tbmage=-1;
}
var that=this;
setTimeout( function() { that.diap() }, this.temp );
}

precision sur le contexte (this)

comme on le voit depuis le debut le mot clee "this" qui traduite en francais donne "ce, cette" est constament present il sert a representé l'objet courant de facon generaliste afin de donner une lisibilité pour chaques objet, dans l'utilisation c'est un pointeur vers l'objet courant.

Perdre le contexte courant est l'un des principaux problemes rencontré en poo et il arrive donc qu'il represente un autre objet qui peut etre une balise html ou bien l'objet windows.

Dans les fonctions nous avons cette syntaxe

 var that=this;
setTimeout( function() { that.diap() }, this.temp );

Si nous avions utilisé this directement,

 setTimeout( function() { this.diap() }, this.temp );

setTimeout faisant partie de l'objet window a son utilisation on se retrouverait dans le contexte de l'objet windows this représenterait la page. Afin de palier a ce probleme il existe deux techniques.

la premiere technique consiste a utiliser une variable intermédiaire qui contient un lien vers le contexte qui nous intéresse this représentera bien notre contexte, c'est ce que fait le code precedent.

la deuxieme technique fait appel a la méthode bind() et permet de conserver le contexte.

Il faut bien ce mettre en tete que la perte du contexte courant est l'un des principaux probleme rencontré.

l'instance

En poo une class est donc instanciable c'est a dire que l'on va pouvoir crée autant de copie de notre constructeur que l'on souhaite, chaque instance d'un constructeur est appelé Objet La syntaxe est la suivante.

new nom_de_la_fonction_a_instancié()

On peut aussi lui affublé un nom afin d'avoir accès au fonction et variables de l'instance de l'objet.

var instance_1=new nom_de_la_fonction_a_instancié();

et on peut rajouté des paramètre qui deviendront des atributs de notre objet.

new nom_de_la_fonction_a_instancié(parametre_1,parametre_2,parametre_3);

Dans notre cas nous allons créer 3 diaporama pour lesquels on précise en paramètre l'id de la balise img associé au diaporama,le array associé au diaporama le répertoire ou se trouve les images et la durée d'attente avant transition. Le tout est placé dans un fonction d'initialisation qui sera appelé par l'évènement onload.

function inimage(){

 var tbdiapo_1=new Array ('d1.jpg','d2.jpg','d3.jpg','d10.jpg','d11.jpg','d12.jpg');
 var tbdiapo_2=new Array ('d4.jpg','d5.jpg');
 var tbdiapo_3=new Array ('d6.jpg','d7.jpg','d8.jpg','d9.jpg');

 new Diaporama('diapo_1',tbdiapo_1,'images/',500);
 new Diaporama('diapo_2',tbdiapo_2,'images/',1000);
 new Diaporama('diapo_3',tbdiapo_3,'images/',1500);
}

onload=init;

Comme dit précédemment les paramètres déclaré seront récupéré par l'objet crée

A noter que l'on peut paramétré chaques diaporamas de façon différente comme la durée, d'attente le répertoire ou se trouves les images ou le nombre d'image et c'est la aussi un des interets de faire de la poo.

On remarquera aussi que le array contenant le nom des image pour chaques diaporama est récupéré par l'instance concerné , il s'agit d'un pointeur vers le array et c'est pour cette raison qu'il n'est pas supprimer.

le script

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
body{
background: black
}
img{
width:12%;
}
</style>
<script type="text/javascript">
function Diaporama( cible,tableau,repertoire,duree){
this.cible=document.getElementById(cible);
this.Tableau=tableau;
this.temp=duree;
this.repertoir_image=repertoire;
this.tbmage=-1;
this.diap();
}
Diaporama.prototype.diap = function(){
this.tbmage++;
this.cible.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
if(this.tbmage==this.Tableau.length-1){
this.tbmage=-1;
}
var that=this;
setTimeout( function() { that.diap() }, this.temp );
}
function inimage(){
var tbimagea=new Array("d7","d7_02","d7_03","d7_04","d7_05","d7_06");
var tbimageb=new Array("d8","d8_02","d8_03","d8_04","d8_05","d8_06");
var tbimagec=new Array("d10","d10_02","d10_03","d10_04","d10_05","d10_06");
new Diaporama('diapo_1',tbdiapo_1,'images/',500);
new Diaporama('diapo_2',tbdiapo_2,'images/',1000);
new Diaporama('diapo_3',tbdiapo_3,'images/',1500);
}
typeof window.addEventListener == 'undefined' ? window.attachEvent("onload",inimage) : window.addEventListener("load",inimage, false);
</script>
</head>
<body>
<div style='width:90%;margin:auto''>
<img id='diapo_1'/>
<img id='diapo_2' />
<img id='diapo_3' />
</div>
</body>
</html>

conclusion

Finalement on se rend compte que la façon de programmer en poo reste similaire a la programmation fonctionnel, la seul qui chose qui peut poser problème quand on commence a faire de la poo c'est la perte du contexte this mis a par ca il est tout de même plus simple de créé un objet instanciable. Généralement quand j' ai besoin d'un script qui doit être instancié je le développe sans utiliser la poo et c'est uniquement quand je l' ai fini que je le retranscrit en objet c'est une bonne méthode quand on débute en poo afin de comprendre les mécanismes de la poo et ses pièges mais si vous préférez travailler directement en poo ne vous gênez pas sa évite la retranscription.

un peut plus loin

Nous allons pousser plus loin notre diaporama en créant dynamiquement la partie html et en ajoutant des evenements .

création dynamique des éléments

actuellement la partie html se compose d'un div conteneur et des trois balises img avec un id correspondant au trois diaporama.

<div>
        <img id='diapo_1'/>
        <img id='diapo_2' />
        <img id='diapo_3' />
</div>

le but est donc de cree la balise img de chaques diaporama instancié dynamiquement et pour ce faire rien de plus simple que de créé une méthode suplémentaire. avant tout il faudra supprimer les balise img du conteneur et lui donné un id nous l'appeleront 'conteneur'. On ajoutera un attribut suplementaire qui contiendra un lien vers le conteneur.

<div id='conteneur'>

</div>

la création se fait de manière classique en utilisant document.createElement('element') on donne le chemin de la première image et enfin on insère la balise dans le div conteneur.

il n'est point besoin de donne un id a la balise car au moment de la création de la balise on cree l'attribut this.Image auquel on lui assigne l'élément créé pour simplifier l'attribut this.Image pointera ver la balise img en consequence le contenu de l'attribut this.Image ne sera plus déclaré dans la classe mais dans le prototype de creation.

la creation de l'instance sera modifier en remplacant l'id de la balise img par celui du conteneur

new Diaporama('conteneur',tbdiapo_1,500,'ff')
new Diaporama('conteneur',tbdiapo_2,1000,'gg')
new Diaporama('conteneur',tbdiapo_3,1500,'hh')

la fonction de création se fera en utilisant la méthode du prototype. On appelle la fonction de création au moment de l'instanciation, le lancement du diaporama se fera donc apres la creation du html il faut donc remplacer this.diap() par this.creation() qui sera le nom de la fonction qui cree le html et this.diap() sera placé ala fin de cette meme fonction afin de lancer le diaporama;

function Diaporama(cible,tableau,duree){
 
 this.Imag='';
 this.Tableau=tableau;
 this.temp=duree;
 this.tbmage=-1;
 this.conteneur=document.getElementById(cible);
  
 this.creation();
 }

la fonction de creation

Diaporama.prototype.creation = function(){

 this.Image=document.createElement('img');
 this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
 document.getElementById('conteneur').appendChild(this.Image);
 
 this.diap();
}

ajout d'évènement

pour la suite nous ajoutons un évènement onmouseover afin d'arreter le diaporama qui sera survolé en stoppant le timer avec clearTimeout et un évènement onmouseout afin de le relancé par un simple appel a la fonction.

les évènements seront ajouté juste après la création des élément dans le même prototype, l'arret du timer et la relance du diaporama se feront a l'intérieur d'une fonction anonyme afin de simplifier la conservation du contexte courant ( this ) et enfin dans la classe on créera un attribut supplémentaire qui pointera vers le timer afin de le stoppé .

Diaporama.prototype.creation = function(){

 this.Image=document.createElement('img');
 this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
 document.getElementById('conteneur').appendChild(this.Image);
 
 var lui=this;
 this.Image.onmouseout=function(){lui.diap()};
 this.Image.onmouseover=function(){clearTimeout(lui.timer)};
 
 this.diap();
}

le script

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
body{
background: black
}
img{
width:12%;
}
</style>
<script type="text/javascript">
function Diaporama( tb,repertoire, tps ){
this.Tableau=tb;
this.temp=tps;
this.repertoir_image=repertoire;
this.tbmage=-1;
this.timer='';
this.creation();
}
Diaporama.prototype.diap = function(){
this.tbmage++;
this.Image.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
if(this.tbmage==this.Tableau.length-1){
this.tbmage=-1;
}
var lui=this;
this.timer=setTimeout( function() { lui.diap(); }, this.temp );
}
Diaporama.prototype.creation = function(){
this.Image=document.createElement('img');
this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
document.getElementById('conteneur').appendChild(this.Image);
var lui=this;
this.Image.onmouseout=function(){lui.diap()};
this.Image.onmouseover=function(){clearTimeout(lui.timer)};
this.diap();
}
function inimage(){
var tbimagea=new Array("d7","d7_02","d7_03","d7_04","d7_05","d7_06");
var tbimageb=new Array("d8","d8_02","d8_03","d8_04","d8_05","d8_06");
var tbimagec=new Array("d10","d10_02","d10_03","d10_04","d10_05","d10_06");
new Diaporama(tbimagea,'images/',600);
new Diaporama(tbimageb,'images/',400);
new Diaporama(tbimagec,'images/',300);
}
typeof window.addEventListener == 'undefined' ? window.attachEvent("onload",inimage) : window.addEventListener("load",inimage, false);
</script>
</head>
<body>
<div style='width:90%;margin:auto' id='conteneur'>
</div>
</body>
</html>

vous pouvez voir le résultat sur cette page diaporama en poo

autres méthodes de creation d'objet

Object.create

Object.create() fait partie de la specification ECMAScript 5.1 et a été implémenté dans JavaScript 1.8.5 il permet d'instancié un objet sans passer par new a partir d' un objet literal ce qui n'est pas le cas avec new..Nous allons donc voir comment faire pour instancier nos objet en se rapprochant le plus du principe de new sans new. nous verrons en premier la methode classique qui utilise une fonction constructeur et la seconde methode qui utilise un objet littéral mais qui n'est pas supporter par ie8 et inférieur.

methode par prototype

avant toute chose Object.create a besoin comme parametre l'objet qui sera le prototype on vas donc creer une fonction vide ou plus precisémént on va vider la fonction Diaporama mais on conserve le prototype et toute ces méthodes celle du diaporama. il faudra uniquement définir le contenu de nos objet.

la syntaxe sera la suivante

Object.create(Diaporama.prototype)

ce qui donne

function Diaporama(){
 
}

function diap_instance( tb,repertoire, tps ){

var ob=Object.create(Diaporama.prototype);
 ob.Tableau=tb
 ob.repertoir_image=repertoire
 ob.temp=tps
 ob.tbmage=-1
 ob.creation()
}

et donc pour chaques diaporama il ne reste plus qu'a appeler la fonction diap_instance() en lui precisant les parametres.

 var tbimagea=new Array("d7","d7_02","d7_03","d7_04","d7_05","d7_06");
 var tbimageb=new Array("d8","d8_02","d8_03","d8_04","d8_05","d8_06");
 var tbimagec=new Array("d10","d10_02","d10_03","d10_04","d10_05","d10_06");

 diap_instance(tbimagea,'images/',600);
 diap_instance(tbimageb,'images/',400);
 diap_instance(tbimagec,'images/',300);

le script

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">

body{
background: black
}

img{
width:12%;
}
</style>

<script type="text/javascript">

function diap_instance( tb,repertoire, tps ){

var ob=Object.create(Diaporama.prototype);
 ob.Tableau=tb
 ob.repertoir_image=repertoire
 ob.temp=tps
 ob.tbmage=-1
 ob.creation()
 
}

function Diaporama(){
 
}

Diaporama.prototype.diap = function(){

 this.tbmage++;
 this.Image.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
 if(this.tbmage==this.Tableau.length-1){
  this.tbmage=-1;
 }
 var lui=this;
 this.timer=setTimeout( function() { lui.diap(); }, this.temp );
}

Diaporama.prototype.creation = function(){

 this.Image=document.createElement('img');
 this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
 document.getElementById('conteneur').appendChild(this.Image);
 
 var lui=this;
 
 this.Image.onmouseout=function(){lui.diap()};
 this.Image.onmouseover=function(){clearTimeout(lui.timer)};
 
 this.diap();
}

function inimage(){

 var tbimagea=new Array("d7","d7_02","d7_03","d7_04","d7_05","d7_06");
 var tbimageb=new Array("d8","d8_02","d8_03","d8_04","d8_05","d8_06");
 var tbimagec=new Array("d10","d10_02","d10_03","d10_04","d10_05","d10_06");
  
 diap_instance(tbimagea,'images/',600);
 diap_instance(tbimageb,'images/',400);
 diap_instance(tbimagec,'images/',300);
}

typeof window.addEventListener == 'undefined' ? window.attachEvent("onload",inimage) : window.addEventListener("load",inimage, false);

</script>
</head>
<body style='background:black'>
<div style='width:90%;margin:auto' id='conteneur'>

</div>

</body>
</html>

méthode avec objet littéral

en Javascript on peut créer un objet de façon littéral cette objet se comporte de la même façon qu'un objet instancié mais ils est uniques.

Un objet littéral fonctionne de la même manière qu'un tableau associatif on associe a un nom soit une valeur qui est un attribut de l'objet soit une fonction anonyme qui est une méthode de l'objet. chaque paires est séparé par une virgule.

un objet littéral ce créé de cette façon.

var un_littéral={valeur_1:'bonjour',valeur_2':coucou',valeur_3:function(){alert('pouet')}

mais pour simplifier grandement la lisibilité on fait un saut de ligne après la virgule

var un_litteral={

   valeur_1:'bonjour',

   valeur_2':coucou',

   methode_1:function(){

       alert('pouet')
       alert(this.valeur_1)
     
   }
}

avant d'utiliser Object.create() on vas d’abord recrée le contenu du prototype en le transformant en objet littéral;

var Diaporama={

 creation : function(){

  this.Image=document.createElement('img');
  this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
  document.getElementById('conteneur').appendChild(this.Image);
  
  var lui=this;
  
  this.Image.onmouseout=this.diap.bind(this);
  this.Image.onmouseover=function(){clearTimeout(lui.timer)}
  
  this.diap();
 },

 diap : function(){

  this.tbmage++;
  this.Image.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
  if(this.tbmage==this.Tableau.length-1){
   this.tbmage=-1
  }
  var lui=this;
  this.timer=setTimeout( function() { lui.diap(); }, this.temp );
 }
}

a ce stade il ne reste plus qu'a créer les instances en précisant que l'objet litteral sera le prototype

 var ob=Object.create(Diaporama);

et enfin on déclare pour chaques instances les attributs mis en paramètre de fonction et on concerve l'appel a la fonction de creation.

function diap_instance( tb,repertoire, tps ){

var ob=Object.create(Diaporama);
 ob.Tableau=tb;
 ob.repertoir_image=repertoire;
 ob.temp=tps;
 ob.creation();
return ob
}

le return ob ne sert a rien dans notre cas il servirait si on voulais avoir accès au attribut et méthodes d'une instance en l'assignant a une variable.

et pour ce qui est de l'instanciation elle reste inchangé

function inimage(){

 var tbimagea=new Array("d7","d7_02","d7_03","d7_04","d7_05","d7_06");
 var tbimageb=new Array("d8","d8_02","d8_03","d8_04","d8_05","d8_06");
 var tbimagec=new Array("d10","d10_02","d10_03","d10_04","d10_05","d10_06");

        diap_instance(tbimagea,'images/',600);
        diap_instance(tbimageb,'images/',400);
        diap_instance(tbimagec,'images/',300);

en utilisant objet.create avec un objet latéral la fonction constructeur est inexistante.

le script

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">

body{
background: black
}

img{
width:12%;
}
</style>

<script type="text/javascript">

function diap_instance( tb,repertoire, tps ){

var ob=Object.create(Diaporama);
 ob.Tableau=tb;
 ob.repertoir_image=repertoire;
 ob.temp=tps;
 ob.creation();
 return ob
 
}

var Diaporama={

 Tableau:'',
 temp:'',
 repertoir_image : '',
 tbmage:-1,
 Image:'',
 timer:'',
 
 creation : function(){

  this.Image=document.createElement('img');
  this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
  document.getElementById('conteneur').appendChild(this.Image);
  
  var lui=this;
  
  this.Image.onmouseout=this.diap.bind(this);
  this.Image.onmouseover=function(){clearTimeout(lui.timer)}
  
  this.diap();
 },

 diap : function(){

  this.tbmage++;
  this.Image.src=this.repertoir_image+this.Tableau[this.tbmage]+'.jpg';
  if(this.tbmage==this.Tableau.length-1){
   this.tbmage=-1
  }
  var lui=this;
  
  this.timer=setTimeout( function() { lui.diap(); }, this.temp );
 }
}

function inimage(){

 var tbimagea=new Array("d7","d7_02","d7_03","d7_04","d7_05","d7_06");
 var tbimageb=new Array("d8","d8_02","d8_03","d8_04","d8_05","d8_06");
 var tbimagec=new Array("d10","d10_02","d10_03","d10_04","d10_05","d10_06");
  
 diap_instance(tbimageb,'images/',400);
 diap_instance(tbimagec,'images/',300);
}

typeof window.addEventListener == 'undefined' ? window.attachEvent("onload",inimage) : window.addEventListener("load",inimage, false);

</script>
</head>
<body style='background:black'>
<div style='width:90%;margin:auto' id='conteneur'>

</div>

</body>
</html>

Object.create n'est pas supporté pas les anciens navigateurs tel que ie8 on peut rajouter ce que l'on appel un polyfiil qui n'est autre qu'une fonction js qui permet d'émuler objet.create polyfill que j'ai trouvé sur mdn et qui teste si Objet.create est supporté et si ce n'est pas le cas vas utiliser faire en sorte que le navigateur le supporte le script doit etre mis entre les balises script

<script>
if (typeof Object.create != 'function') {
    (function () {
        var F = function () {};
        Object.create = function (o) {
            F.prototype = o;
            return new F();
        };
    })();
}
</script>

utilisation de class (es6)

presentation

ecma script 6 est la norme pour javascript elle a éte officialisé en jun 2015 elle permet d'utiliser une class plutot qu'une fonction pour la creation d'objet.

Pour la suite nous allons une fois de plus modifier notre diaporama pour qu'il fonctionne avec les class.

ce qui change

on retrouve des nouveaux mot class contructor super.

la class

c'est le conteneur de l'objet dans sa globalité.

le constructeur

définit avec le mot constructor et délimité par des accolades c'est ce que l'on appelait auparavant la fonction constructeur donc toutes les méthodes et tous les attributs propres a un objet seront créé a cette endroit.

les méthodes (fonctions) du prototype

Elles sont créé hors du constructeur mais toujours a l'intérieur de la classe sans utiliser le mot clée function seul le nom de la méthode est mis.

ce qui ne change pas

Meme si la syntaxe est differente a l'intanciation l'objet cree utilise la poo par prototype.

Il existe d'autre différences dont une qui est l'impossibilité de cree des attributs au prototype .

Les principale raison de l'implantation des class est la simplicité de création de ce que l'on appel l'heritage et aussi une accessibilité rapide de la poo en javascript pour les personnes venant d'autre langage de programation utilisant la poo par class.

le code

<!DOCTYPE html>
<html lang="en">
<head>
<mata charset="UTF-8">

<script type="text/javascript">

class Diaporama {

 constructor(cible,tableau,duree) {
 
  this.Imag='';
  this.Tableau=tableau;
  this.temp=duree;
  this.tbmage=-1;
  this.conteneur=document.getElementById(cible);
  
  this.creation();
 }
 
 diap(){
  
  this.tbmage++;
  this.Image.src=this.Tableau[this.tbmage];
  
  if(this.tbmage==this.Tableau.length-1){
   this.tbmage=-1
  }
  
  setTimeout(this.diap.bind(this), this.temp);
 }

 creation(){
 
 this.Image=document.createElement('img');
 this.Image.src=this.repertoir_image+this.Tableau[0]+'.jpg';
 this.conteneur.appendChild(this.Image);
 
 var lui=this;
 this.Image.onmouseout=function(){lui.diap()};
 this.Image.onmouseover=function(){clearTimeout(lui.timer)};
 
 this.diap();
}
 
}


function inimage(){

 var tbdiapo_1=new Array ('d1.jpg','d2.jpg','d3.jpg','d10.jpg','d11.jpg','d12.jpg')
 var tbdiapo_2=new Array ('d4.jpg','d5.jpg')
 var tbdiapo_3=new Array ('d6.jpg','d7.jpg','d8.jpg','d9.jpg')
 
 new Diaporama('conteneur',tbdiapo_1,500,'ff')
 new Diaporama('conteneur',tbdiapo_2,1000,'gg')
 new Diaporama('conteneur',tbdiapo_3,1500,'hh')
 
}

onload=inimage

</script>
</head>
<body >

<div style='width:500px;margin:auto;margin-top:150px' id='conteneur'>

</div>

</body>
</html>
A voir également
Ce document intitulé « la poo en javascript par un exemple pratique et visuel » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous