open

Les objets en Javascript

#1 Notre objectif : utiliser les objets open

Quel que soit le langage, concevoir une application orientée objet nécessite des compétences particulières.

Notre objectif dans ce tutoriel ce sera de comprendre ce que sont les objets et d'apprendre à les utiliser. La plupart du temps un concepteur de page Web en HTML se contente d'utiliser des objets natifs (fournis par le langage) ou des objets fournis par des interfaces. En particulier celle avec le document HTML.

#2 Qu'est ce qu'un objet ? open

On va prendre un exemple concret. Supposons que l'on veuille gérer une boutique en ligne d'articles de sport. Tous les articles ont des caractéristiques communes. Ils correspondent tous à un produit, ils ont tous une référence et ils ont tous un prix hors taxes. Ils ont aussi une fonctionnalité commune car pour tous les articles on aura besoin de calculer le prix toutes taxes comprises.

Au niveau du code on voit bien que pour chaque article on va avoir besoin d'une variable produit pour stocker le nom du produit, d'une autre variable reference pour stocker la référence et d'une dernière variable prixHT pour stocker le prix hors taxes.

Ces variables sont liées entre elles car elles correspondent à un article. Et ces variables ont une valeur pour chaque article.

L'idée c'est de regrouper ces variables et de les encapsuler dans une boîte que l'on va appeler Article. Les variables dans la boîte ne sont pas initialisées. Cette boîte c'est un modèle. Elle contient aussi la fonction calculerPrixTTC.

Synoptique d'un objet

A chaque fois que l'on va vouloir créer un article on va prendre la boîte et on va mettre des valeurs dedans pour affecter chaque propriétés.

On se sert de la boîte Article pour créer article1
Prendre une instance d'un objet
On se sert à nouveau de la boîte Article pour créer article2
Prendre une autre instance d'un objet

Cette boîte c'est un objet. Les variables vont constituer les propriétés de l'objet Article. La fonction calculerPrixTTC constituera la méthode de l'objet Article.

article1 et article2 sont des instances de l'objet Article

La création d'un objet puis de ses instances

Ci-dessous on va coder notre "boîte". On va d'abord déclarer Article puis en prendre deux instances article1 et article2. On va le faire en utilisant les "classes Javascript" qui sont disponibles depuis la version ECMAScript 6ième édition 2015. Cette façon de procéder va nous permettre dans un premier temps d'éviter les prototypes.

  1. Prenez Sublime text et créez sur le bureau un fichier que vous appelez Article.html. Faites !>script puis tab. Donnez le titre Article à la page web.
  2. Maintenant vous allez déclarer votre objet. Vous devez utiliser le mot réservé class et le faire suivre de Article. L'usage veut que l'on mette une majuscule à Article qui signale que c'est un objet.
  3. Ensuite vous devez déclarer une fonction constructeur (constructor en anglais). La fonction constructeur sera appelée au moment de la création d'une instance. C'est cette fonction qui va initialiser la boîte. Vous devez prévoir des paramètres de déclaration et vous allez avoir besoin d'un paramètre pour chaque valeur à affecter à une propriété. En général on donne le même nom à un paramètre de déclaration et à la propriété.
  4. Vous devez utiliser le mot réservé this pour affecter chaque propriété de votre objet avec sa valeur d'instance. Par exemple this.produit = produit. Ici this.produit accède à la propriété produit. this est une adresse mémoire, c'est ce qu'on appelle un pointeur. Il y a une allocation de mémoire dynamique pour chaque instance de l'objet. this est en quelque sorte l'adresse mémoire de l'instance. Vous stockerez dans cette zone mémoire les valeurs d'instances qui seront passées en paramètres d'appel du constructeur au moment de la création de l'instance. A la fin du constructeur c'est comme si il y avait un return de this. Et la valeur de ce pointeur sera affectée à l'instance de l'objet.
  5. Ensuite vous programmez la méthode. Notez que c'est une fonction et que vous n'utilisez pas le mot réservé function. L'interpréteur Javascript s'y retrouvera car la déclaration est dans un objet. Notez aussi que vous utilisez une des propriétés prixHT par l'intermédiaire de this soit this.prixHT. this est visible dans tout l'objet.
  6. Ensuite vous devez prendre les instances et pour cela vous faites new sur Article() en passant les données de l'instance soit Article('Sac à dos',645020,35). La fonction constructor est appelée avec les données d'instance comme paramètres d'appel. Ce n'est pas vous qui faites cet appel directement. C'est le new qui le déclenche (il ne fait pas que ça).
  7. Vous prenez une deuxième instance. Donc notez bien que les variables article1 et article2 reçoivent chacune un pointeur. Maintenant, faites Open in Browser dans Sublime. Prenez la console. Tapez article1 et visualisez les valeurs d'instance. Notez qu'il n'y a pas que ça dans l'instance.
  8. Faites typeof article1 dans la console et vous voyez s'afficher object. C'est un nouvelle valeur retournée par typeof. On ne l'a jamais vu ensemble. Elle correspond à un objet bien sûr mais souvenez vous avant tout que c'est un pointeur.
Tester le code

Ajoutez un console.log() de this et un autre de typeof de this. Vous constatez :

  1. typeof this renvoie object.
  2. this pointe bien sur l'instance. En fait vous passez un pointeur au console.log() et il vous affiche l'objet pointé.
Tester le code

Ci-dessous vous avez une illustration qui résume ce que l'on a fait à savoir la déclaration de l'objet d'un côté et la prise des instances de l'objet de l'autre.

Prendre des instances de l'objet
Prendre des instances d'un objet

Comment se servir d'un objet parent pour créer un objet enfant

La deuxième façon d'utiliser la boîte c'est de s'en servir de base de départ afin d'enrichir sa structure de données et de lui ajouter de nouvelles fonctionnalités. De cette façon on crée une nouvelle boîte, un nouvel objet. Le nouvel objet est appelé objet enfant. Il récupère ainsi la structure de données et les fonctionnalités de l'objet parent. Cette sorte de transmission s'appelle l'héritage en Programmation Orientée Objet (POO).

Construire un objet enfant à partir d'un objet parent
Construire un objet par héritage

Supposons que l'on veuille mettre des articles en promotion dans notre boutique en ligne. Ces articles ont les mêmes caractéristiques que les autres articles à savoir un nom de produit, une référence et un prixHT. Mais en plus ils ont une propriété supplémentaire c'est la remise que l'on va faire sur le PrixTTC. On a également besoin d'une méthode pour calculer le prix de vente en promotion de ces articles. Comme on ne veut pas tout recommencer, on va se servir de l'objet Article.

Etant donné que nous avons à notre disposition en Javascript un mécanisme d'héritage on va récupérer les propriétés et méthodes de l'objet Article pour construire un nouvel objet Promo. Et pour Promo on va lui ajouter une propriété remise et une méthode calculerPrixPromo().

Construire l'objet Promo à partir de l'objet Article
Construire Promo à partir de Article

On va construire un nouvel objet Promo qui va être une extension de l'objet Article. On dit aussi que l'objet Promo est un enfant de l'objet Article. Pour cela :

  1. Sauvegardez le fichier Article.html sous un nouveau nom Promo.html. Vous allez travailler maintenant sur Promo.html. Supprimez les deux instances article1 et article2.
  2. Déclarez la classe Promo comme une extension de la classe Article. Vous devez utiliser le mot réservé extends.
  3. Déclarez un constructeur pour la classe Promo. Ce constructeur doit prendre comme paramètres de déclaration l'ensemble des propriétés des deux objets puisque les propriétés des deux objets doivent être affectées au moment de l'instanciation. Les propriétés produit, reference et prixHT du parent et la propriété remise de l'enfant.
  4. Dans ce constructeur, vous devez appeler le constructeur de la classe parent en utilisant le mot réservé super. Vous passez les paramètres de déclaration du parent.
  5. Ensuite vous initialisez la propriété de l'enfant. Ici il n'y a que remise. Vous utilisez à nouveau this qui pointe ici sur une future instance de Promo.
  6. Ensuite vous passez au codage de la méthode calculerPrixPromo. Pour cela vous avez besoin d'accéder à la méthode calculerPrixTTC du parent et pour y accéder vous utilisez à nouveau le mot réservé super.
  7. Ensuite vous pouvez instancier Promo en prenant bien soin de mettre tous les paramètres d'appel.
Tester le code

#3 Comment créer un objet littéral ? open

Vous avez une autre façon de procéder pour créer un objet. C'est un objet spécifique qui s'appelle un objet littéral. Dans ce cas, le plus souvent, le programmeur crée d'abord un objet vide en utilisant les accolades. Puis il utilise les capacités de gestion dynamique des propriétés de Javascript. En effet Javascript vous permet d'ajouter des propriétés au fur et à mesure de votre besoin. Vous pouvez également en supprimer.

Pour ajouter une propriété il suffit d'affecter une nouvelle propriété.

Pour supprimer une propriété il faut utiliser l'opérateur delete.

  1. Avec Sublime faites CTRL+N pour créer un nouveau fichier puis CTRL+S pour le sauvegarder sur le bureau. Vous lui donnez le nom de Litteral.html. Faites !>script puis tab. Donnez le titre Litteral à la page web.
  2. Déclarez une instance article de l'objet vide en utilisant les accolades.
  3. Ajoutez la propriété produit en affectant article.produit à 'Sac à dos'.
  4. Ajoutez la propriété reference en affectant article.reference à 645020.
  5. Ajouter la propriété prixHT en affectant article.prixHT à 35.
  6. Ajouter la propriété stock en affectant article.stock à 10.
  7. Supprimez la propriété reference avec un delete sur article.reference.
  8. Faites un console.log() pour afficher l'objet.
  9. Faites un clic droit dans Sublime puis choisissez Open in Browser. Puis CTRL+SHIFT+I pour accéder à la console.
  10. Vérifiez la liste des propriétés.
Tester le code

Vous pouvez aussi utiliser la syntaxe JSON pour initialiser une instance. Chaque propriété est composée d'un couple nom et valeur. Le nom et la valeur sont séparés par le caractère deux points. Chaque couple nom et valeur est séparé par une virgule.

  1. Effacez ce qu'il y a dans l'élément script de Litteral.html sauf le console.log()
  2. Déclarez un objet en utilisant la syntaxe JSON.
  3. Faites un clic droit dans Sublime puis choisissez Open in Browser. Puis CTRL+SHIFT+I pour accéder à la console.
  4. Vérifiez la liste des propriétés.
Tester le code

#4 Héritage par prototype open

Reprenez le fichier Article.html, avec la console examinez l'instance article1.

Tester le code

Vous constatez que les trois propriétés produit reference et prixHT ont été placées dans l'instance et que la méthode calculerPrixTTC() a été placée dans une autre propriété __proto__. Cette autre propriété c'est ce que l'on appelle le prototype. C'est en fait un objet prototype. Faites typeof article1.__proto__ et vous obtenez object.

calculerPrixTTC est dans le prototype de Article
Prototype de l'objet parent

La méthode calculerPrixTTC() est dans l'objet prototype de l'objet Article. Les instances partagent l'objet prototype et du coup la méthode calculerPrixTTC(). Notez que de cette manière le code n'est pas dupliqué.

article1 et article2 partagent le proto d'Article
article1 et article2 partage le proto d'Article
Les deux pointeurs __proto__ des instances sont égaux
égalité des __proto__ testée sur la console

Cet objet prototype a la charge de mettre à disposition les propriétés qu'il contient. Il les met à la disposition d'autres objets. Si vous regardez dans le premier __proto__ vous constatez qu'il contient un autre __proto__ qui lui pointe sur le prototype d'un Object. Ensuite ça s'arrête. Object est l'objet parent de tous les autres objets.

Liste chaînée d'objet prototype
Liste chaînée de prototype

Ca veut dire qu'un objet prototype contient un pointeur vers un autre objet prototype. On a donc une liste chaînée d'objets prototypes qui se termine par le prototype de l'objet Object.

  1. Reprenez le fichier Promo.html, avec la console examinez l'instance de promo.
  2. Vous constatez que le prototype de Promo pointe sur celui d'Article. C'est ici que l'héritage se fait.
Tester le code
le prototype de l'objet Promo
Prototype de l'objet enfant

Je résume le fonctionnement : si une propriété est demandée, l'interpréteur regarde d'abord dans l'instance. Si elle n'est pas dans l'instance il la cherche dans la chaîne de prototype.

#5 Tester si une propriété existe dans un objet open

Pour faire cela nous avons deux moyens :

  1. La méthode hasOwnProperty(). Elle renvoie true si la propriété se trouve dans l'instance. Elle renvoie false si la propriété se trouve dans la chaîne de prototype, y compris le prototype de l'objet avec lequel on a construit l'instance.
  2. L'opérateur in. Il permet de tester si la propriété se trouve dans l'instance ou bien dans la chaîne de prototype.

On va tester ces deux moyens d'abord sur la propriété remise et sur la méthode calculerPrixPromo() qui appartiennent à l'objet Promo, puis sur la propriété valueOf qui elle appartient à l'objet Object.

Tester le code

#6 Parcourir la liste des propriétés open

Tester le code

#7 Egalité entre deux instances du même objet ? open

La notion d'égalité entre deux instances d'un objet dépend de ce que l'objet contient. Prenons le cas par exemple de deux instances d'un objet tableau. Les deux instances seront égales si les éléments des deux tableaux sont égaux deux à deux pour chaque index des tableaux. Si cette égalité a du sens pour l'objet en question c'est le programmeur qui implantera une méthode pour tester si deux instances sont égales .

#8 Fabriquer un objet avec un constructeur open

Cette méthode était la méthode utilisée avant la version 6 de Javascript. On peut dire que :

  • c'est une méthode qui laisse pas mal de choses à la charge du programmeur. Par exemple la mise en place de la chaîne des prototypes.
  • c'est une méthode qui nécessite la compréhension parfaite des mécanismes internes du Javascript en terme de prototype, de fonction constructeur...etc
  • les mécanismes de base restent les mêmes dans les deux versions. L'utilisation des "classes Javascript" est mise en oeuvre par dessus ces mécanismes de base.
  • si vous souhaitez construire des applications orientées objets en Javascript vous aurez besoin de connaître cette méthode. Vous aurez aussi besoin de compétences en matière de conception orientée objet.

#9 Passer une instance en paramètre d'appel d'une fonction open

Reprenez le fichier Article.html.

On a vu que article1 est un pointeur. Vous allez passer ce pointeur à une fonction. Le pointeur va être passé par copie comme expliqué dans le tuto sur les fonctions. Mais ce pointeur permettra un accès à l'instance et une modification des propriétés de l'instance depuis la fonction.

un pointeur en paramètre d'appel
Un pointeur en paramètre d'appel
Tester le code