diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/fr/learn/javascript/objects | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/fr/learn/javascript/objects')
8 files changed, 1972 insertions, 0 deletions
diff --git a/files/fr/learn/javascript/objects/ajouter_des_fonctionnalités_à_notre_démo_de_balles_rebondissantes/index.html b/files/fr/learn/javascript/objects/ajouter_des_fonctionnalités_à_notre_démo_de_balles_rebondissantes/index.html new file mode 100644 index 0000000000..36232925ec --- /dev/null +++ b/files/fr/learn/javascript/objects/ajouter_des_fonctionnalités_à_notre_démo_de_balles_rebondissantes/index.html @@ -0,0 +1,208 @@ +--- +title: Ajouter des fonctionnalités à notre exercice des balles rebondissantes +slug: >- + Learn/JavaScript/Objects/Ajouter_des_fonctionnalités_à_notre_démo_de_balles_rebondissantes +tags: + - Apprentissage + - CodingScripting + - Débutant + - Evaluation + - JavaScript + - OOJS + - Objet + - Orienté objet +translation_of: Learn/JavaScript/Objects/Adding_bouncing_balls_features +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Dans cet exercice, vous devrez utiliser le jeu des balles rebondissantes de l'article précédent comme base, pour y ajouter de nouvelles fonctionnalitées intéressantes.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td>Avant de vous lancer dans cet exercice, il est fortement conseillé d'avoir vus et compris tous les précédents articles de ce module.</td> + </tr> + <tr> + <th scope="row">Objectifs:</th> + <td>Tester votre connaissance du Javascript orienté objet en conception et en pratique.</td> + </tr> + </tbody> +</table> + +<h2 id="Pour_commencer">Pour commencer</h2> + +<p>Pour commencer, faite une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index-finished.html">index-finished.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">main-finished.js</a> de l'article précédent, dans un nouveau dossier.</p> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez utiliser un site comme <a class="external external-icon" href="http://jsbin.com/">JSBin</a> ou <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a>. Vous pouvez copier vos codes HTML, CSS et JavaScript dans l'un d'entre eux. Si celui que vous utilisez ne possède pas de fenêtres séparées pour les différents langages, ajoutez les dans des balises <code><script></code>/<code><style></code> dans votre code HTML.</p> +</div> + +<h2 id="Le_projet_en_bref">Le projet en bref</h2> + +<p>Notre jeu des balles est assez sympa, mais maintenant il s'agit de le rendre plus interactif en y ajoutant un viseur controlé par l'utilisateur, qui va détruire une balle si il l'a touche. Nous voulons aussi testé votre capacité en programmation orienté objet en créant un object <code>Shape()</code> dont le viseur et les balles peuvent hériter. Pour terminer nous voulons créer un compteur qui permet d'afficher combien de balle il nous reste encore à détruire.</p> + +<p>Ce screenshot vous donne une idée du résultat final:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13875/bouncing-evil-circle.png" style="display: block; margin: 0 auto;"></p> + +<ul> +</ul> + +<p>Si vous voulez en savoir plus regardez l'exemple finit <a href="http://mdn.github.io/learning-area/javascript/oojs/assessment/">finished example</a> (N'en profitez pas pour récupérer le code source !)</p> + +<h2 id="Vos_objectifs">Vos objectifs</h2> + +<p>Cette section décrit ce que vous aurez à faire.</p> + +<h3 id="Créons_nos_nouveaux_objets">Créons nos nouveaux objets</h3> + +<p>Pour commencer, modifions le constructeur de l'objet <code>Ball()</code> pour qu'il devienne le constructeur de <code>Shape()</code> puis créons en un nouveau pour <code>Ball()</code> :</p> + +<ol> + <li>Le constructeur <code>Shape()</code> devra définir les propriétés <code>x</code>, <code>y</code>, <code>velX</code>, et <code>velY</code> de la même manière que le constructeur <code>Ball()</code> auparavent, mais sans les propriétés <code>color</code> et <code>size</code>.</li> + <li><code>Shape()</code> doit aussi définir une nouvelle propriété <code>exists</code>, qui servira à identifier les balles qu'il reste à détruire dans la fenêtre (celles qui n'on pas encore été détruites). Elle doit retourner un booléen (<code>true</code>/<code>false</code>).</li> + <li>Le constructeur <code>Ball()</code> doit hériter des propriétés <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, et <code>exists</code> du constructeur <code>Shape()</code>.</li> + <li><code>Ball()</code> doit aussi définir les propriétés <code>color</code> et <code>size</code>, comme à l'origine.</li> + <li>N'oubliez pas de définir le prototype de <code>Ball()</code> et son constructeur de manière approprié.</li> +</ol> + +<p>Les méthodes <code>draw()</code>, <code>update()</code>, et <code>collisionDetect()</code> doivent fonctionnées comme avant, sans être modifiées.</p> + +<p>Vous devrez ajouter un nouveau paramètre au constructeur <code>new Ball() ( ... )</code> — le paramètre <code>exists</code> doit être le 5ème et être égal à <code>true</code>.</p> + +<p>Vous pouvez recharger la page — Tout doit fonctionner comme avant même après les modifications que vous avez effectuées sur les objets.</p> + +<h3 id="Définition_du_EvilCircle()_(viseur)">Définition du EvilCircle() (viseur)</h3> + +<p>Il est temps de vous équipez ! — le <code>EvilCircle()</code>! Dans notre jeu nous allons créer un viseur, mais nous allons nous servir de l'objet <code>Shape()</code> pour le définir. Vous voudrez certainement en ajouter un (plusieurs) autre plus tard, qu'un autre joueur ou l'ordinateur pourra contrôler. Vous n'irez probablement pas bien loin avec un seul viseur, mais ce sera suffisant pour le moment !</p> + +<p>Le constructeur du <code>EvilCircle()</code> doit hériter des propriétés <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, et <code>exists</code> de <code>Shape()</code>, mais <code>velX</code> et <code>velY</code> doivent toujours être égales à 20.</p> + +<p>Vous devriez utiliser quelque chose comme <code>Shape.call(this, x, y, 20, 20, exists);</code></p> + +<p>Le constructeur doit aussi définir ses propres propriétés:</p> + +<ul> + <li><code>color</code> — <code>'white'</code></li> + <li><code>size</code> — <code>10</code></li> +</ul> + +<p>Une fois de plus, souvenez vous de définir vos propriétés héritées en paramètre du constructeur et de définir le prototype et son constructeur de manière appropriée.</p> + +<h3 id="Définir_les_méthodes_du_EvilCircle()_(viseur)">Définir les méthodes du EvilCircle() (viseur)</h3> + +<p><code>EvilCircle()</code> doit avoir quatre méthodes, comme définie en dessous.</p> + +<h4 id="draw()"><code>draw()</code></h4> + +<p>Cette méthode doit avoir la même fonction que celle de <code>Ball()</code>: soit dessiner l'objet dans le canvas. Elle fonctionnera quasiment de la même manière, copiez la fonction <code>Ball.prototype.draw</code>. Puis appliquez les modifications suivantes:</p> + +<ul> + <li>On ne veut pas que le viseur soit plein, mais qu'il ait seulement un contour. Changez <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> et <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> pour <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle">strokeStyle</a></code> et <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/stroke">stroke()</a></code>.</li> + <li>On voudrait qu'il soit aussi un peu plus épais, pour être plus facile à voir. Pour ça on doit définir un attribut <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth">lineWidth</a></code> à ctx après l'appel à la fonction <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> (avec une valeur de 3).</li> +</ul> + +<h4 id="checkBounds()"><code>checkBounds()</code></h4> + +<p>Cette méthode à la même fonction que la première partie de <code>Ball()</code> <code>update()</code> — Savoir si le viseur va hors de l'écran, et l'arrêter si besoin. Une fois encore, copié la méthode <code>Ball.prototype.update</code>, mais en effectuant quelques changements:</p> + +<ul> + <li>Débarrassez-vous des deux dernières lignes — on a pas besoin de connaître la position du viseur à chaque frame, car nous le déplacerons d'une manière différente comme vous pourrez le voir.</li> + <li>Dans les conditions en <code>if()</code> , si la condition retourne true on ne veut pas modifier (update) les propriétés <code>velX</code>/<code>velY</code>; mais plutôt changer les valeurs de <code>x</code>/<code>y</code> de manière à ce que le viseur revienne doucement dans l'écran. Ajouter ou soustraire de manière appropriée la taille (<code>size)</code> du viseur sera suffisant.</li> +</ul> + +<h4 id="setControls()"><code>setControls()</code></h4> + +<p>Cette méthode ajoute un écouteur d'évènement <code>onkeydown</code> à l'objet <code>window</code> ce qui permettra en enfonçant certaine touche du clavier de déplacer le viseur dans la fenêtre. Insérez le code suivant dans la méthode:</p> + +<pre class="brush: js">var _this = this; +window.onkeydown = function(e) { + if (e.keyCode === 65) { + _this.x -= _this.velX; + } else if (e.keyCode === 68) { + _this.x += _this.velX; + } else if (e.keyCode === 87) { + _this.y -= _this.velY; + } else if (e.keyCode === 83) { + _this.y += _this.velY; + } + }</pre> + +<p>Quand une touche est enfoncée, la propriété <a href="/en-US/docs/Web/API/KeyboardEvent/keyCode">keyCode</a> de l'objet event est consultée pour savoir quelle touche est enfoncée. Si c'est une des touches spécifiée, alors le viseur ce déplacera à gauche, à droite, en haut ou en bas.</p> + +<ul> + <li>Pour un point bonus, faite apparaître à quel touche correspond le code de celle que l'utilisateur a enfoncé.</li> + <li>Pour un second point bonus, pouvez vous nous dire pourquoi nous devons définir <code>var _this = this;</code> de cette façon ? Cela à quelque chose à voir avec la portée des fonction.</li> +</ul> + +<h4 id="collisionDetect()"><code>collisionDetect()</code></h4> + +<p>Cette méthode fonctionne d'une manière similaire à <code>Ball()</code> <code>collisionDetect()</code>, copier celle-ci pour vous en servir comme base. Il y a deux différences:</p> + +<ul> + <li>Dans la condition extérieure <code>if</code>, nous n'avons plus besoin de vérifier si la balle actuellement dans la boucle est celle actuellement surveiller — Parce que ce n'est plus une balle, mais notre viseur ! A la place, on doit tester si la balle visée existe (avec quelle propriété pourrez vous faire cela?). Si elle n'existe pas, c'est qu'elle a déjà été détruite, on a donc pas besoin de la vérifier encore une fois.</li> + <li>Dans la condition intérieur <code>if</code>, on ne souhaite plus changer un élément de couleur lorsqu'une collision est détéctée — A la place, on veut détruire les balles qui entre en collision avec le viseur (encore une fois, comment pensez-vous faire cela ?).</li> +</ul> + +<h3 id="Insérer_le_viseur_dans_notre_programme">Insérer le viseur dans notre programme</h3> + +<p>Maintenant que nous avons définit notre viseur, on a besoin de le faire apparaître à l'écran. Pour ce faire on doit appliquer quelques modifications à la fonction <code>loop()</code>.</p> + +<ul> + <li>Premièrement, créons une nouvelle instance de l'objet viseur (en spécifiant les paramètres nécessaire), et appelons sa méthode <code>setControls()</code>. On doit seulement effectuer ses deux actions une seule fois, pas à chaque itération.</li> + <li>Au moment où l'on boucle à travers toutes les balles et que l'on appelle les méthodes <code>draw()</code>, <code>update()</code>, et <code>collisionDetect()</code> pour chacune d'entre elle, faite de manière à ce que ces fonctions soit appelées seulement si la balle existe.</li> + <li>Appellez les méthodes de l'instance du viseur <code>draw()</code>, <code>checkBounds()</code>, et <code>collisionDetect()</code> à chaque itération de la boucle.</li> +</ul> + +<h3 id="Implémenter_le_compteur_de_score">Implémenter le compteur de score</h3> + +<p>Pour implémenter le compteur de score, suivez les étapes suivantes:</p> + +<ol> + <li>Dans votre fichier HTML, ajoutez un élement {{HTMLElement("p")}} qui contiendra le texte suivant "Ball count: ", juste en dessous de l'élément {{HTMLElement("h1")}} .</li> + <li>Dans votre fichier CSS, ajouter les règlesz suivantes: + <pre class="brush: css">p { + position: absolute; + margin: 0; + top: 35px; + right: 5px; + color: #aaa; +}</pre> + </li> + <li>Dans votre JavaScript, effectuez les modifications suivante: + <ul> + <li>Créez une variable qui contiendra la référence vers le paragraphe.</li> + <li>Stocker et afficher le nombre de balle présentent à l'écran.</li> + <li>Incrémentez le compteur de balle à chaque fois qu'une balle apparait à l'écran.</li> + <li>Décrementez le compteur à chaque fois qu'une balle est détruite par le viseur.</li> + </ul> + </li> +</ol> + +<h2 id="Conseils_et_astuces">Conseils et astuces</h2> + +<ul> + <li>Cet exercice est un bon challenge. Prenez le temps de faire et de comprendre chaque étape.</li> + <li>Ce serait une bonne idée de garder une copie de chaque étape lorsque vous arrivez à la faire marcher correctement, pour vous y réferrer si vous n'arrivez plus à progresser ensuite.</li> +</ul> + +<h2 id="Evaluation">Evaluation</h2> + +<p>Si vous effectuez cette évalutation dans le cadre d'un cours, vous devriez pouvoir fournir votre travail à votre professeur/mentor pour correction. Si vous apprenez par vous même, vous pouvez obtenir la correction sur <a href="https://discourse.mozilla.org/t/adding-features-to-our-bouncing-balls-demo-assessment/24689">discussion thread for this exercise</a>, ou sur <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC channel sur <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Tout d'abord effectuez cet exercice — vous n'obtiendrez jamais rien en trichant !</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</p> + +<h2 id="Dans_ce_Module">Dans ce Module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> diff --git a/files/fr/learn/javascript/objects/basics/index.html b/files/fr/learn/javascript/objects/basics/index.html new file mode 100644 index 0000000000..6d7276b7b1 --- /dev/null +++ b/files/fr/learn/javascript/objects/basics/index.html @@ -0,0 +1,258 @@ +--- +title: 'Les bases de JavaScript, orienté objet' +slug: Learn/JavaScript/Objects/Basics +tags: + - API + - Apprendre + - Débutant + - JavaScript + - Objet + - Syntaxe + - this +translation_of: Learn/JavaScript/Objects/Basics +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Dans ce premier article sur les objets JavaScript, nous verrons la syntaxe des objets JavaScript ainsi que quelques fonctionnalités JavaScript déjà aperçues dans les cours précédents, rappelant que beaucoup de fonctionnalités que vous utilisez sont en fait des objets.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Connaissances informatiques de base, connaissances basiques concernant HTML et CSS, bonnes connaissances des bases de JavaScript (cf. <a href="/fr/docs/Learn/JavaScript/First_steps">les premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">les briques de construction</a>).</td> + </tr> + <tr> + <th scope="row">Objectifs :</th> + <td>Comprendre les théories de base derrière la programmation orientée objet, comment l'appliquer à JavaScript, et comment travailler avec des objets JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Les_bases_de_lobjet">Les bases de l'objet</h2> + +<p>Un objet est une collection de données apparentées et/ou de fonctionnalités (qui, souvent, se composent de plusieurs variables et fonctions, appelées propriétés et méthodes quand elles sont dans des objets). Prenons un exemple pour voir à quoi cela ressemble.</p> + +<p>Pour commencer, faites une copie locale de notre fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a>. Il contient peu de choses : un élément {{HTMLElement("script")}} pour écrire notre code à l'intérieur. Nous utiliserons ces éléments de base pour explorer les bases de la syntaxe objet. Durant cette exemple, vous devriez avoir <a href="/fr/docs/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs#La_console_JavaScript">la console JavaScript des outils de développement</a> ouverte et prête, pour y saisir des commandes.</p> + +<p>Comme souvent dans JavaScript, pour créer un objet, on commence avec la définition et l'initialisation d'une variable. Essayez de mettre le code ci-dessous sous le code déjà écrit de votre fichier JavaScript, puis sauvegardez et rafraichissez la page :</p> + +<pre class="brush: js notranslate">var personne = {};</pre> + +<p>Désormais ouvrez la <a href="/fr/docs/Outils/Console_JavaScript#Ouvrir_la_Console_du_navigateur">console JavaScript</a> de votre navigateur, saisissez <code>personne</code> à l'intérieur, et appuyez sur <kbd>Entrée</kbd>. Vous devriez obtenir le résultat suivant :</p> + +<pre class="brush: js notranslate">[object Object]</pre> + +<p>Félicitations, vous avez créé votre premier objet ! Mais c'est un objet vide, on ne peut pas faire grand-chose avec. Modifions notre objet pour qu'il ressemble à ceci :</p> + +<pre class="brush: js notranslate">var personne = { + nom: ['Jean', 'Martin'], + age: 32, + sexe: 'masculin', + interets: ['musique', 'skier'], + bio: function() { + alert(this.nom[0] + ' ' + this.nom[1] + ' a ' + this.age + ' ans. Il aime ' + this.interets[0] + ' et ' + this.interets[1] + '.'); + }, + salutation: function() { + alert('Bonjour ! Je suis ' + this.nom[0] + '.'); + } +}; +</pre> + +<p>Après avoir sauvegardé et rafraîchit la page, essayez d'entrer les lignes suivantes dans le champ de saisie <code>input</code> :</p> + +<pre class="brush: js notranslate">personne.nom +personne.nom[0] +personne.age +personne.interets[1] +personne.bio() +personne.salutation()</pre> + +<p>Vous avez désormais des données et des fonctionnalités dans votre objet, et vous pouvez y accéder avec une une syntaxe simple et claire !</p> + +<div class="note"> +<p><strong>Note :</strong> Si vous avez des difficultés pour le faire fonctionner, comparez votre code avec notre version — voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-finished.html">oojs-finished.html</a> (ou <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-finished.html">voir en action</a>). Une erreur courante, quand on commence avec les objets, est de mettre une virgule après la dernière propriété — ce qui provoque une erreur.</p> +</div> + +<p>Alors, comment ça fonctionne ? Un objet est fait de plusieurs membres, qui ont chacun un nom (par exemple <code>nom</code> et <code>age</code> ci-dessus) et une valeur (par exemple. <code>['Jean', 'Martin']</code> et <code>32</code>).</p> + +<p>Chaque paire de nom/valeur doit être séparée par une virgule, et le nom et la valeur de chaque membre sont séparés par deux points. La syntaxe suit ce schéma :</p> + +<pre class="brush: js notranslate">var monObjet = { + nomDuMembre1: valeurDuMembre1, + nomDuMembre2: valeurDuMembre2, + nomDuMembre3: valeurDuMembre3 +}</pre> + +<p>La valeur d'un membre dans un objet peut être n'importe quoi — dans notre objet <code>personne</code>, nous avons du texte, un nombre, deux tableaux et deux fonctions. Les quatre premières éléments sont des données appelées <strong>propriétés</strong> de l'objet, et les deux derniers éléments sont des fonctions qui utilisent les données de l'objet pour faire quelque chose, et sont appelées des <strong>méthodes</strong> de l'objet.</p> + +<p>Dans cet exemple, l'objet est créé grâce à un<strong> objet littéral</strong> : on écrit littéralement le contenu de l'objet pour le créer. On distinguera cette structure des objets instanciés depuis des classes, que nous verrons plus tard.</p> + +<p>C'est une pratique très courante de créer un objet en utilisant un objet littéral : par exemple, quand on envoie une requête au serveur pour transférer des données vers une base de données.</p> + +<p>Envoyer un seul objet est bien plus efficace que d'envoyer ses membres de manière individuelle, et c'est bien plus simple de travailler avec un tableau quand on veut identifier des membres par leur nom.</p> + +<h2 id="Notation_avec_un_point">Notation avec un point</h2> + +<p>Ci-dessus, on accède aux membres de l'objet en utilisant la <strong>notation avec un point</strong>.</p> + +<p>Le nom de l'objet (<code>personne</code>) agit comme un <strong>espace de noms</strong> (ou <em>namespace</em> en anglais) — il doit être entré en premier pour accéder aux membres <strong>encapsulés</strong> dans l'objet. Ensuite, on écrit un point, puis le membre auquel on veut accéder — que ce soit le nom d'une propriété, un élément d'un tableau, ou un appel à une méthode de l'objet. Par exemple :</p> + +<pre class="brush: js notranslate">personne.age +personne.interets[1] +personne.bio()</pre> + +<h3 id="Sous-espaces_de_noms">Sous-espaces de noms</h3> + +<p>Il est même possible de donner un autre objet comme valeur d'un membre de l'objet. Par exemple, on peut essayer de changer la propriété <code>nom</code> du membre et la faire passer de</p> + +<pre class="brush: js notranslate">nom: ['Jean', 'Martin'],</pre> + +<p>à</p> + +<pre class="brush: js notranslate">nom : { + prenom: 'Jean', + nomFamille: 'Martin' +},</pre> + +<p>Ici, nous avons bien créé un <strong>sous-espace de noms</strong>. Ça a l'air compliqué, mais ça ne l'est pas. Pour accéder à ces élements, il suffit de chaîner une étape de plus avec un autre point. Essayez ceci :</p> + +<pre class="brush: js notranslate">personne.nom.prenom +personne.nom.nomFamille</pre> + +<p><strong>Important </strong>: à partir de maintenant, vous allez aussi devoir reprendre votre code et modifier toutes les occurrences de :</p> + +<pre class="brush: js notranslate">nom[0] +nom[1]</pre> + +<p>en</p> + +<pre class="brush: js notranslate">nom.prenom +nom.nomFamille</pre> + +<p>sinon vos méthodes ne fonctionneront plus.</p> + +<h2 id="Notation_avec_les_crochets">Notation avec les crochets</h2> + +<p>Il y a une autre façon d'accéder aux membres de l'objet : la notation avec les crochets. Plutôt que d'utiliser ceci :</p> + +<pre class="brush: js notranslate">personne.age +personne.nom.prenom</pre> + +<p>Vous pouvez utiliser :</p> + +<pre class="brush: js notranslate">personne['age'] +personne['nom']['prenom']</pre> + +<p>Cela ressemble beaucoup à la façon d'accéder aux éléments d'un tableau et c'est bien la même chose — au lieu d'utiliser un indice numérique pour sélectionner un élément, on utilise le nom associé à chaque valeur d'un membre. Ce n'est pas pour rien que les objets sont parfois appelés tableaux associatifs : ils associent des chaînes de caractères (les noms des membres) à des valeurs, de la même façon que les tableaux associent des nombres à des valeurs.</p> + +<h2 id="Définir_les_membres_dun_objet">Définir les membres d'un objet</h2> + +<p>Jusqu'ici, nous avons vu comment <strong>accéder</strong> aux membres d'un objet. Vous pouvez aussi <strong>modifier</strong> la valeur d'un membre de l'objet en déclarant simplement le membre que vous souhaitez modifier(en utilisant la notation avec le point ou par crochet), comme ceci :</p> + +<pre class="brush: js notranslate">personne.age = 45 +personne['nom']['nomFamille'] = 'Rabuchon'</pre> + +<p>Essayez de saisir ces deux lignes précédentes, puis accédez à nouveau aux membres pour voir ce qui a changé :</p> + +<pre class="brush: js notranslate">personne.age +personne['nom']['nomFamille']</pre> + +<p>Définir les membres ne s'arrête pas à mettre à jour la valeur de propriétés ou méthodes existantes; <strong>vous pouvez aussi créer de nouveaux membres</strong>. Essayez ceci :</p> + +<pre class="brush: js notranslate">personne['yeux'] = 'noisette' +personne.auRevoir = function() { alert("Bye bye tout le monde !"); }</pre> + +<p>Vous pouvez maintenant tester vos nouveaux membres :</p> + +<pre class="brush: js notranslate">personne['yeux'] +personne.auRevoir()</pre> + +<p>Un des aspects pratiques de la notation par crochet est qu'elle peut être utilisée pour définir dynamiquement les valeurs des membres, mais aussi pour définir les noms. Imaginons que nous voulions que les utilisateurs puissent saisir des types de valeurs personnalisées pour les données des personnes, en entrant le nom du membre et sa valeur dans deux champs <code>input</code>. On pourrait avoir ses valeurs comme ceci :</p> + +<pre class="brush: js notranslate">var monNomDeDonnee = nomInput.value +var maValeurDeDonnee = valeurNom.value</pre> + +<p>On peut alors ajouter le nom et la valeur du nouveau membre de l'objet <code>personne</code> comme ceci :</p> + +<pre class="brush: js notranslate">personne[monNomDeDonnee] = maValeurDeDonnee</pre> + +<p>Pour le tester, essayez d'ajouter les lignes ci-dessous dans votre code, juste après le crochet fermante de l'objet <code>personne</code> :</p> + +<pre class="brush: js notranslate">var monNomDeDonnee = 'hauteur' +var maValeurDeDonnee = '1.75m' +personne[monNomDeDonnee] = maValeurDeDonnee</pre> + +<p>Sauvegardez, rafraîchissez et entrez le texte suivant dans le champ de saisie (l'élément <code>input</code>) :</p> + +<pre class="brush: js notranslate">personne.hauteur</pre> + +<p>Nous n'aurions pas pu construire ce membre avec la notation avec un point, car celle-ci n'accepte qu'un nom et pas une variable pointant vers un nom.</p> + +<h2 id="Quest-ce_que_«_this_»">Qu'est-ce que « <code>this</code> » ?</h2> + +<p>Vous avez dû remarquer quelque chose d'un peu étrange dans vos méthodes. Celle-ci, par exemple :</p> + +<pre class="brush: js notranslate">salutation: function() { + alert('Bonjour! Je suis ' + this.nom.prenom + '.'); +}</pre> + +<p>Vous vous demandez probablement ce que signifie « <code>this</code> ». Le mot-clé <code>this</code> se réfère à l'objet courant dans lequel le code est écrit — dans notre cas, <code>this</code> est l'équivalent de <code>personne</code>. Alors, pourquoi ne pas écrire <code>personne</code> à la place ? Comme vous le verrez dans l'article <a href="/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS">la programmation JavaScript orientée objet pour les débutants</a>, <code>this</code> est très utile — il permet de s'assurer que les bonnes valeurs sont utilisées quand le contexte d'un membre change (on peut par exemple avoir deux personnes, sous la forme de deux objets, avec des noms différents).</p> + +<p>Essayons d'illustrer nos propos par une paire d'objet <code>personne</code> simplifiée :</p> + +<pre class="brush: js notranslate">var personne1 = { + nom: 'Christophe', + salutation: function() { + alert('Bonjour ! Je suis ' + this.nom + '.'); + } +} + +var personne2 = { + nom: 'Bruno', + salutation: function() { + alert('Bonjour ! Je suis ' + this.nom + '.'); + } +}</pre> + +<p>Dans ce cas, <code>personne1.salutation()</code> affichera "Bonjour ! Je suis Christophe.", tandis que <code>personne2.salutation()</code> affichera "Bonjour ! Je suis Bruno." alors que le code est le même dans les deux cas. Comme expliqué plus tôt, <code>this</code> est égal à l'objet dans lequel se situe le code. Ce n'est pas très utile quand on écrit des objets littéraux à la main, mais ça prend tout son sens quand on génère des objets dynamiques (avec des constructeurs par exemple).</p> + +<h2 id="Vous_utilisiez_des_objets_depuis_le_début_!">Vous utilisiez des objets depuis le début !</h2> + +<p>Tout au long de ces exemples, vous vous êtes probablement dit que la notation avec un point vous était très familière. C'est parce que vous l'avez utilisée tout au long du cours ! À chaque fois que vous avez travaillé avec un exemple qui utilise une API ou un objet JavaScript natif, nous avons utilisé des objets. Ces fonctionnalités sont construites exactement comme les objets que nous avons manipulés ici, mais sont parfois plus complexes que dans nos exemples.</p> + +<p>Ainsi, quand vous utilisez une méthode comme :</p> + +<pre class="brush: js notranslate">maChaineDeCaracteres.split(',');</pre> + +<p>Vous utilisez une méthode disponible dans une instance du type {{jsxref("String")}}. Dès que vous créez une chaîne de caractères dans votre code, cette chaîne est automatiquement créée comme une instance de <code>String</code> et possède donc plusieurs méthodes/propriétés communes.</p> + +<p>Quand vous accédez au DOM (<em>Document Object Model</em> ou « modèle objet du document ») avec <code>document</code> et des lignes telles que :</p> + +<pre class="brush: js notranslate">var monDiv = document.createElement('div'); +var maVideo = document.querySelector('video');</pre> + +<p>Vous utilisez une méthode disponible dans l'instance de la classe {{domxref("Document")}}. Pour chaque page web chargée, une instance de <code>Document</code> est créée, appelée <code>document</code> et qui représente la structure entière de la page, son contenu et d'autres caractéristiques telles que son URL. Encore une fois, cela signifie qu'elle possède plusieurs méthodes/propriétés communes.</p> + +<p>C'est également vrai pour beaucoup d'autres objets/API natifs que vous avez utilisé — {{jsxref("Array")}}, {{jsxref("Math")}}, etc.</p> + +<p>On notera que les objets/API natifs ne créent pas toujours automatiquement des instances d'objet. Par exemple, <a href="/fr/docs/Web/API/Notifications_API">l'API Notifications</a> — qui permet aux navigateurs modernes de déclencher leurs propres notifications — vous demande d'instancier vous-même une nouvelle instance d'objet en utilisant le constructeur pour chaque notification que vous souhaitez lancer. Essayez d'entrer le code ci-dessous dans la console JavaScript :</p> + +<pre class="brush: js notranslate">var maNotification = new Notification('Bonjour !');</pre> + +<p>Nous verrons les constructeurs dans un prochain article.</p> + +<div class="note"> +<p><strong>Note</strong> : On peut voir le mode de communication des objets comme un <strong>envoi de message</strong>. Quand un objet a besoin d'un autre pour faire une action, souvent il va envoyer un message à un autre objet via l'une de ses méthode et attendre une réponse, qui retournera une valeur.</p> +</div> + +<h2 id="Résumé">Résumé</h2> + +<p>Félicitations, vous avez terminé notre premier article sur les objets JavaScript — vous devriez maintenant mieux comprendre comment on travaille avec des objets en JavaScript. Vous avez pu créer vos propres objets basiques. Vous devriez aussi voir que les objets sont très pratiques pour stocker des données et des fonctionnalités. Si on ne passe pas par un objet et qu'on a une variable différente pour chaque propriété et méthode de notre objet <code>personne</code>, cela sera inefficace et frustrant et vous prendrez le risque de créer des conflits avec d'autres variables et fonctions du même nom.</p> + +<p>Les objets permettent de conserver les informations de façon sûre, enfermées dans leur propre « paquet », hors de danger.</p> + +<p>Dans le prochain article, nous commencerons à voir la théorie de la programmation orientée objet (POO) et comment utiliser ces techniques en JavaScript.</p> + +<p>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</p> diff --git a/files/fr/learn/javascript/objects/heritage/index.html b/files/fr/learn/javascript/objects/heritage/index.html new file mode 100644 index 0000000000..9359b6f4ee --- /dev/null +++ b/files/fr/learn/javascript/objects/heritage/index.html @@ -0,0 +1,260 @@ +--- +title: L'héritage au sein de JavaScript +slug: Learn/JavaScript/Objects/Heritage +tags: + - Apprendre + - Article + - Débutant + - Héritage + - JS Orienté Objet + - JavaScript + - Objet + - Programmation orientée objet + - Prototype +translation_of: Learn/JavaScript/Objects/Inheritance +--- +<div> +<p>{{LearnSidebar}}</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> + +<p>Les présentations ayant été faites pour les concepts du JavaScript orienté objet, cet article détaille comment il est possible de créer une classe fille qui hérite des propriétés de sa classe mère. Nous verrons ensuite quelques conseils quant à l'utilisation du JavaScript orienté objet.</p> + +<table> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td>Une connaissance générale de l'informatique, des notions d'HTML et CSS, une connaissance des bases en JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction</a>) ainsi que des notions de JavaScript orienté objet (JSOO) (voir <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>).</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre comment implémenter l'héritage en JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Héritage_prototypique">Héritage prototypique</h2> + +<p>Nous avons déjà vu le concept d'héritage en action, nous avons vu comment la chaîne de prototypage fonctionnait, et comment les propriétés de cette chaîne sont lues de manière ascendante. En revanche,nous n'avons utilisé pratiquement que quelques fonctionnalités déjà intégrées dans le navigateur pour le faire. Comment créer un objet JavaScript qui hérite d'un autre objet ?</p> + +<p>Certains pensent que JavaScript n'est pas un véritable langage orienté objet. Dans les langages orientés objets classiques, on définit des classes objet et on peut ensuite définir laquelle hérite d'une autre (voir <a href="http://www.tutorialspoint.com/cplusplus/cpp_inheritance.htm">C++ inheritance</a> en anglais pour des exemples simples). JavasScript utilise une approche différente : les objets héritant d'un autre n'ont pas de fonctionnalités copiées d'un autre objet, au lieu de ça, ils héritent des fonctionnalités via les liens de la chaîne de prototypage (on parle alors d'un <strong>héritage prototypique</strong>).</p> + +<p>Voyons comment cela se passe avec un exemple concret.</p> + +<h2 id="Pour_commencer">Pour commencer</h2> + +<p>Tout d'abord, faites une copie du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> (voir la <a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">démo</a>). Vous y trouverez le constructeur <code>Personne()</code> que nous avons utilisé jusque là dans l'ensemble des modules, néanmoins il y a un léger changement : nous n'avons défini que les attributs au sein du constructeur.</p> + +<pre>function Personne(prenom, nom, age, genre, interets) { + this.nom = { + prenom, + nom + }; + this.age = age; + this.genre = genre; + this.interets = interets; +};</pre> + +<p>L'ensemble des méthodes est défini dans le prototype :</p> + +<pre>Personne.prototype.saluer = function() { + alert('Salut! Je suis ' + this.nom.prenom + '.'); +};</pre> + +<p>Essayons de créer une classe <code>Professeur</code> similaire à celle que nous avons utilisée jusqu'ici dans les autres modules d'initiations à l'approche objet. Ainsi, cette classe hérite de <code>Personne</code> mais possède aussi :</p> + +<ol> + <li>Un nouvel attribut <code>matière</code> — qui contiendra la matière que le professeur enseigne.</li> + <li>Une méthode <code>saluer</code> un peu plus élaborée, qui sera un peu plus formelle que la méthode de base, cela sera plus approprié, lorsque le professeur s'adrressera à des étudiants, par exemple.</li> +</ol> + +<h2 id="Définissons_le_constructeur_Professeur()">Définissons le constructeur Professeur()</h2> + +<p>La première chose à faire est de créer le constructeur <code>Professeur()</code> via l'ajout du code suivant :</p> + +<pre>function Professeur(prenom, nom, age, genre, interets, matiere) { + Personne.call(this, prenom, nom, age, genre, interets); + + this.matiere = matiere; +}</pre> + +<p>Cela ressemble beaucoup au constructeur <code>Personne</code> mais il y a quelque chose que nous n'avons pas encore vu : la fonction <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a></code>. Cette fonction permet d'appeler une fonction définie ailleurs dans le contexte actuel. Le premier paramètre spécifie la valeur de <code>this</code> que l'on souhaite utiliser lors que l'on utilisera la fonction, les paramètres suivants seront les paramètres qui pourront être passés en arguments lorsqu'elle sera appelée.</p> + +<p>Nous voulons que le constructeur <code>Professeur()</code> aie les mêmes attributs que <code>Personne()</code>, nous les spécifions donc dans l'appel fait via la fonction <code>call()</code>.</p> + +<p>La dernière ligne au sein du constructeur sert simplement à définir l'attribut <code>matière</code> que les professeurs enseignent, ce qui n'est pas valable pour les personnes génériques.</p> + +<p>Notez que nous aurions très bien pu écrire tout simplement ceci :</p> + +<pre>function Professeur(prenom, nom, age, genre, interets, matiere) { + this.nom_complet = { + prenom, + nom + }; + this.age = age; + this.genre = genre; + this.interets = interets; + this.matiere = matiere; +}</pre> + +<p>Cependant cela aurait eu pour effet de redéfinir les attributs à nouveau, sans les hériter de <code>Personne()</code>, ce qui n'est pas vraiment le but que nous voulons atteindre lorsque l'on parle de l'héritage, cela rajoute aussi des lignes de code inutiles.</p> + +<p> </p> + +<h3 id="Hériter_d'un_constructeur_sans_paramètres">Hériter d'un constructeur sans paramètres</h3> + +<p>Notez que si les valeurs des propriétés du constructeur dont vous héritez ne proviennent pas de paramètres, vous n'avez nullement besoin de les specifier comme arguments additionnels dans l'appel de la fonction <code>call()</code>. Donc, par exemple, si vous avez quelque chose d'aussi simple que ceci :</p> + +<pre><code>function Brick() { + this.width = 10; + this.height = 20; +}</code></pre> + +<p>Vous pouvez hériter des propriétés <code>width</code> et <code>height</code> en procédant comme ceci (Mais également en suivant bien sûr les différentes étapes décrites ci dessous) :</p> + +<pre><code>function BlueGlassBrick() { + Brick.call(this); + + this.opacity = 0.5; + this.color = 'blue'; +}</code></pre> + +<p>Notez que nous n'avons spécifié que <code>this</code> au sein de <code>call()</code> — Aucun autre paramètre n'est requis puisque nous n'héritons ici d'aucune propriété provenant de la classe parente qui soit spécifiée via paramètres. </p> + +<h2 id="Définir_le_prototype_de_Professeur()_et_son_constructeur_référent.">Définir le prototype de Professeur() et son constructeur référent.</h2> + +<p>Pour le moment tout va bien, mais nous avons un petit problème. Nous avons défini un nouveau constructeur et ce dernier possède une propriété <code>prototype</code>, qui par défaut ne contient qu'une référence à la fonction constructrice elle même. En revanche il ne contient pas les méthodes de la propriété <code>prototype</code> du constructeur <code>Personne()</code>. Pour le constater, vous pouvez par exemple entrer <code>Professeur.prototype.constructor</code> dans la console JavaScript pour voir ce qu'il en est. Le nouveau constructeur n'a en aucun cas hérité de ces méthodes. Pour le constater, comparez les sorties de <code>Personne.prototype.saluer</code> et de <code>Professeur.prototype.saluer</code></p> + +<p>Notre classe <code>Professeur()</code> doit hériter des méthodes définies dans le prototype de <code>Personne()</code>. Aussi comment procéder pour obtenir ce résultat ?</p> + +<p>Ajoutez la ligne suivante à la suite du bloc de code que nous venons d'ajouter :</p> + +<pre>Professeur.prototype = Object.create(Personne.prototype);</pre> + +<ol> + <li>Ici, notre ami <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> vient nous aider à nouveau. Dans ce cas, on l'utilise afin de créer un nouvel objet que nous assignons à <code>Professeur.prototype</code>. Le nouvel objet possède <code>Personne.prototype</code> désormais comme son prototype et héritera ainsi, si et quand le besoin se fera sentir, de toutes les méthodes disponible sur <code>Personne.prototype</code>. </li> + <li>Nous avons également besoin de faire encore une chose avant de continuer. Après avoir ajouté la ligne précédente, le constructeur du prototype de <code>Professeur()</code> est désormais équivalent à celui de <code>Personne()</code>, parce que nous avons défini <code>Professeur.prototype</code> pour référencer un objet qui hérite ses propriétés de <code>Personne.prototype</code> ! Essayez, après avoir sauvegardé votre code et rechargé la page, d'entrer <code>Professeur.prototype.constructor</code> dans la console pour vérifier.</li> + <li>Cela peut devenir problématique, autant le corriger dès maintenant. C'est possible via l'ajout de la ligne de code suivante à la fin : + <pre>Professeur.prototype.constructor = Professeur;</pre> + </li> + <li> + <p>A présent, si vous sauvegardez et rafraichissez après avoir écrit <code>Professeur.prototype.constructor</code>, cela devrait retourner <code>Professeur()</code>, et en plus nous héritons maintenant de <code>Personne()</code> !</p> + </li> +</ol> + +<h2 id="Donner_au_prototype_de_Professeur()_une_nouvelle_fonction_saluer()">Donner au prototype de Professeur() une nouvelle fonction saluer()</h2> + +<p>Pour terminer notre code, nous devons définir une nouvelle fonction <code>saluer()</code> sur le constructeur de <code>Professeur()</code>.</p> + +<p>La façon la plus facile d'accomplir cela est de la définir sur le prototype de Professeur() — ajoutez ceci à la suite de votre code :</p> + +<pre>Professeur.prototype.saluer = function() { + var prefix; + + if (this.genre === 'mâle' || this.genre === 'Mâle' || this.genre === 'm' || this.genre === 'M') { + prefix = 'M.'; + } else if (this.genre === 'femelle' || this.genre === 'Femelle' || this.genre === 'f' || this.genre === 'F') { + prefix = 'Mme'; + } else { + prefix = ''; + } + + alert('Bonjour. Mon nom est ' + prefix + ' ' + this.nom_complet.nom + ', et j\'enseigne ' + this.matiere + '.'); +};</pre> + +<p>Ceci affiche la salutation du professeur, qui utilise le titre de civilité approprié à son genre, au moyen d'une instruction conditionnelle.</p> + +<p> </p> + +<h2 id="Exécuter_l'exemple">Exécuter l'exemple</h2> + +<p>Une fois tout le code saisi, essayez de créer une instance d'objet <code>Professeur()</code> en ajoutant à la fin de votre JavaScript (ou à l'endroit de votre choix) :</p> + +<pre>var professeur1 = new Professeur('Cédric', 'Villani', 44, 'm', ['football', 'cuisine'], 'les mathématiques');</pre> + +<p>Sauvegardez et actualisez, et essayez d'accéder aux propriétés et méthodes de votre nouvel objet <code>professeur1</code>, par exemple :</p> + +<pre>professeur1.nom_complet.nom; +professeur1.interets[0]; +professeur1.bio(); +professeur1.matiere; +professeur1.saluer();Ffa</pre> + +<p>Tout cela devrait parfaitement fonctionner. Les instructions des lignes 1,2,3 et 6 accèdent à des membres hérités de la classe générique <code>Personne()</code> via son constructeur, tandis que la ligne 4 accède de façon plus spécifique à un membre qui n'est disponible que via le constructeur de la classe spécialisée <code>Professeur()</code>.</p> + +<p><strong>Note</strong>: Si vous rencontrez un problème afin de faire fonctionner ce code comparez le à notre <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">version finalisée</a> (Ou regarder tourner <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">notre demo en ligne</a>).</p> + +<p>La méthode que nous avons détaillée ici n'est pas la seule permettant de mettre en place l'héritage de classes en JavaScript, mais elle fonctionne parfaitement et elle vous permet d'avoir une bonne idée de comment implémenter l'héritage en JavaScript.</p> + +<p>Vous pourriez également être intéressé par certaines des nouvelles fonctionnalités de {{glossary("ECMAScript")}} qui nous permettent de mettre en place l'héritage d'une façon beaucoup plus élégante en JavaScript (Voir <a href="/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a>). Nous ne les avons pas développées ici parce qu'elles ne sont actuellement pas supportées par tous les navigateurs. Toutes les autres constructions dont nous avons discuté dans cette série d'articles sont supportées par IE9 et les versions moins récentes et il existe des méthodes qui prennent plus en charge les navigateurs moins récents.</p> + +<p>Un moyen habituel est d'utiliser les librairies JavaScript — La plupart des options populaires ont une sélection de fonctionnalités disponibles pour réaliser l'héritage plus facilement et plus rapidement.</p> + +<p><a href="http://coffeescript.org/#classes">CoffeeScript</a> par exemple fournit les fonctionnalités <code>class</code>, <code>extends</code>, etc.</p> + +<h2 id="Un_exercice_plus_complexe.">Un exercice plus complexe.</h2> + +<p>Dans notre <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">section sur la programmation orientée objet</a> nous avons également inclus une classe <code>Etudiant</code> comme un concept qui hérite de toutes les fonctionnalités de la classe <code>Personne</code>, et qui a également une méthode <code>saluer()</code> differente de celle de <code>Personne</code> qui est beaucoup moins formelle que la méthode <code>saluer()</code> de <code>Professeur()</code>. Jetez un oeil à ce à quoi ressemble la méthode <code>saluer()</code> de la classe <code>Etudiant</code> dans cette section et essayez d'implémenter votre propre constructeur <code>Etudiant()</code> qui hérite de toutes les fonctionnalités de <code>Personne()</code> et la fonction <code>saluer()</code> différente.</p> + +<p><strong>Note</strong>: Si vous rencontrez un problème afin de faire fonctionner ce code comparez le à notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html">version finalisée</a> (Ou regarder tourner <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">notre demo en ligne</a>).</p> + +<h2 id="Résumé_sur_les_membres_de_l'Objet">Résumé sur les membres de l'Objet</h2> + +<p>Pour résumer, vous avez de façon basique trois types de propriétés/méthodes à prendre en compte :</p> + +<ol> + <li>Celles définies au sein d'un constructeur et passées en paramètres aux instances de l'objet. Celles là ne sont pas difficiles à repérer — Dans votre propre code personnalisé, elles sont les membres définis en utilisant les lignes comme <code>this.x = x</code> ; Dans les codes préconstruits propres aux navigateurs, ils sont les membres seulement accessibles aux instances d'objet (usuellement créés en appelant un constructeur via l'utilisation du mot clé <code>new</code>, exemple : <code>var myInstance = new myConstructor()</code>).</li> + <li>Celles définies directement sur les constructeurs eux mêmes et accessibles uniquement sur les constructeurs. Celles là sont communément présentes uniquement dans les objets préconstruits des navigateurs et sont reconnus par le fait d'être directement chaînées sur un constructeur et non sur une instance. Par exemple, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>.</li> + <li>Celles définies sur un prototype de constructeur qui sont héritées par toutes les instances des classes d'objet. Celles là incluent n'importe quel membre défini sur un prototype de constructeur, exemple : <code>myConstructor.prototype.x()</code>.</li> +</ol> + +<p>Si vous êtes encore dans la confusion par rapport aux différents types ne vous inquiétez pas c'est normal — vous êtes encore entrain d'apprendre et la familiarité apparaîtra avec la pratique.</p> + +<h2 id="Quand_devez-vous_utiliser_l'héritage_en_JavaScript">Quand devez-vous utiliser l'héritage en JavaScript?</h2> + +<p>Particulièrement après ce dernier article, vous pourriez penser "woa c'est compliqué". Bien, vous avez vu juste, prototypes et héritages représentent une partie des aspects les plus complexes de JavaScript, mais une bonne partie de la puissance et de la flexibilité de JavaScript vient de sa structure Objet et de l'héritage et il est vraiment très important de comprendre comment cela fonctionne. </p> + +<p>D'une certaine manière, vous utilisez l'héritage à plein temps — Que vous utilisiez différentes fonctionnalités d'une WebAPI , ou une méthode/propriété définie par défaut sur un objet prédéfini du navigateur que vous invoquez sur vos chaînes de caractères, tableaux etc., vous utilisez de façon implicite l'héritage. </p> + +<p>En termes d'utilisation de l'héritage dans votre propre code, vous ne l'utiliserez probablement pas si souvent et spécialement pour débuter avec, et dans les petits projets — C'est une perte de temps d'utiliser les objets et l'héritage par amour pour cette pratique quand vous n'en avez pas besoin. Mais à mesure que les bases de votre code s'élargissent vous trouverez cette façon de faire probablement très utile. Si vous trouvez utile et plus pratique de commencer en créant un certain nombre d'objets spécialisés partageant les mêmes fonctionnalités, alors créer un objet générique qui contiendra toutes les fonctionnalités communes dont les objets spécialisés hériteront vous apparaîtra être une pratique peut être plus confortable et efficace par la suite. </p> + +<p><strong>Note</strong>: A cause de la manière dont JavaScript fonctionne, avec la chaîne de prototype, etc., le partage de fonctionnalités entre objet est souvent appelée <strong>délégation</strong> — Les objets spécialisés délèguent cette fonctionnalité à l'objet de type générique. C'est certainement beaucoup plus précis que de l'appeler héritage, puisque la fonctionnalité "héritée" n'est pas copiée dans les objets qui "héritent". Au contraire, elle demeure dans l'objet générique.</p> + +<p>Lorsque vous utilisez l'héritage, il est conseillé de ne pas avoir trop de degrés d'héritage et de toujours garder minutieusement trace de l'endroit où vous définissez vos propriétés et méthodes. Il est possible de commencer à écrire un code qui modifie temporairement les prototypes des objets prédéfinis du navigateur mais vous ne devriez pas le faire à moins que n'ayiez une très bonne raison. Trop de degrés d'héritages peut conduire à une confusion sans fin et une peine sans fin quand vous essayez de déboguer un tel code. </p> + +<p>En définitive, les objets sont juste une autre forme de réutilisation de code comme les fonctions et les boucles avec leurs propres rôles et avantages. Si vous trouvez utile de créer un lot de variables et fonctions relatives et que vous voulez les retracer ensemble et les empaqueter de façon ordonnée, un objet est une bonne idée. Les objets sont également très utiles quand vous souhaitez passer une collection de données d'un endroit à un autre. Toutes ces choses peuvent être accomplies sans l'utilisation d'un constructeur ou de l'héritage. Si vous n'avez besoin que d'une seule instance, l'utilisation d'un simple objet littéral serait certainement un choix beaucoup plus judicieux et vous n'avez certainement pas besoin de l'héritage.</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Cet article a couvert le reste du coeur de la théorie du JSOO et des syntaxes que nous pensons que vous devriez connaître maintenant. A cet stade vous devriez comprendre l'objet JavaScript et les bases de la POO, les prototypes et l'héritage par prototype, comment créer les classes (constructeurs) et les instances d'objet, ajouter des fonctionnalités aux classes, et créer des sous classes qui héritent d'autres classes. </p> + +<p>Dans le prochain article, nous jetterons un regard sur comment travailler avec le (JSON), un format commun d'échange de données écrit en utilisant les objets JavaScript.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — Un site interactif d'appentissage très utile pour en savoir plus sur les Objets.</li> + <li><a href="https://www.amazon.com/gp/product/193398869X/">Secrets of the JavaScript Ninja</a>, Chapitre 6 — Un bon livre sur les concepts et techniques avancées du JavaScript par John Resig et Bear Bibeault. Le chapitre 6 couvre très bien les divers aspects des prototypes et de l'héritage ; vous trouverez sûrement facilement une version imprimée ou une version en ligne.</li> + <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes">You Don't Know JS: this & Object Prototypes</a> — Une partie de l'excellente série de manuels sur le JavaScript de Kyle Simpson. Le chapitre 5 en particulier jette un regard beaucoup plus approfondi sur les prototypes que nous ne l'avons fait ici. Nous avons présenté ici une vue simplifiée dans cette série d'articles dédiée aux débutants tandis que Kyle est allé dans les détails les plus profonds et fournit une image beaucoup plus complexe et plus précise.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> + +<p> </p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics">Les bases de l'Objet</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript Orienté Objet pour débutants</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Prototypes d'Objet</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance">L'héritage en JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON">Travailler avec les données JSON</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Construire les Objets dans la pratique</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Ajouter des fonctionnalités à la démo de nos balles bondissantes</a></li> +</ul> + +<p> </p> +</div> + +<p> </p> diff --git a/files/fr/learn/javascript/objects/index.html b/files/fr/learn/javascript/objects/index.html new file mode 100644 index 0000000000..c388ee3b62 --- /dev/null +++ b/files/fr/learn/javascript/objects/index.html @@ -0,0 +1,70 @@ +--- +title: Introduction aux objets JS +slug: Learn/JavaScript/Objects +tags: + - Apprendre + - Article + - Auto-évaluation + - Débutant + - Guide + - JavaScript + - Objets + - Tutoriel +translation_of: Learn/JavaScript/Objects +--- +<div> +<div>{{JsSidebar}}</div> + +<div>{{PreviousNext("Apprendre/JavaScript/Building_blocks", "Learn/JavaScript/Objects/Basics")}}</div> +</div> + +<p class="summary">En JavaScript, la plupart des choses sont des objets, des éléments du cœur de JavaScript, comme les chaînes de caractères et les tableaux, aux interfaces de programmation (APIs) des navigateurs construites sur la base de JavaScript. Vous pouvez même créer vos propres objets pour encapsuler des fonctions liées et des variables au sein de paquets efficaces, et se comportant comme des conteneurs de données. Il est important de comprendre la nature orientée objet du JavaScript si vous souhaitez aller loin dans votre connaissance du langage, aussi, avons-nous fourni ce module afin de vous aider. Ici, nous enseignons la théorie de l’objet et sa syntaxe en détail, ensuite, ce sera à vous de voir comment vous souhaitez créer vos propres objets. </p> + +<h2 id="Prérequis">Prérequis</h2> + +<p>Avant de commencer ce module, vous devriez avoir quelques familiarités avec le HTML et le CSS. Il serait raisonnable de travailler sur les modules <a href="https://developer.mozilla.org/fr/Apprendre/HTML/Introduction_%C3%A0_HTML">Introduction au HTML</a> et <a href="https://developer.mozilla.org/fr/Apprendre/CSS/Introduction_%C3%A0_CSS">Introduction au CSS</a> avant de commencer avec le JavaScript.</p> + +<p>Vous devriez également être familiarisé avec les bases du JavaScript avant de poursuivre en détails avec les objets JavaScript. Avant de commencer ce module, travaillez sur <a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/First_steps">Premiers pas avec JavaScript</a> et <a href="https://developer.mozilla.org/fr/Apprendre/JavaScript/Building_blocks">Les blocs de construction en JavaScript</a>.</p> + +<div class="note"> +<p><strong>Remarque</strong>: Si vous travaillez sur un ordinateur, une tablette ou un autre appareil où vous n’avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer les (la plupart des) exemples de code grâce à un programme en ligne comme <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guides">Guides</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/Basics">Les bases de JavaScript orienté objet</a></dt> + <dd>Dans le premier article concernant les objets JavaScript, nous découvrirons la syntaxe fondamentale d’un objet JavaScript, et nous revisiterons certaines fonctionnalités du JavaScript que nous avions vues précédemment dans le cours, en insistant sur le fait que bon nombre d'éléments précedemment abordés sont en fait des objets.</dd> +</dl> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/JS_orient%C3%A9-objet">JavaScript orienté objet pour les débutants</a><u> </u></dt> + <dd> + <p style="margin-left: 36.0pt;">Après avoir vu les notions de base, nous nous pencherons sur le JavaScript orienté objet (JSOO) — cet article présente une vue basique de la théorie de la programmation orientée objet (POO), et explore ensuite comment le JavaScript émule les classes d’objet via les fonctions des constructeurs et comment créer des instances d’objet.</p> + </dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/Prototypes_Objet">Objets prototypes</a></dt> + <dd> + <p style="margin-left: 36.0pt;">Les prototypes sont des mécanismes par lesquels les objets JavaScript héritent les fonctionnalités d’un autre objet, et ils fonctionnent différemment des mécanismes d’héritage des langages classiques de programmation orientée objet. Dans cet article, nous explorons cette différence, expliquant comment les chaînes de prototypes fonctionnent et jetant un regard sur comment la propriété prototype peut être utilisée pour ajouter des méthodes aux constructeurs existants.</p> + </dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/Heritage">L’héritage au sein de JavaScript</a></dt> + <dd> + <p style="margin-left: 36.0pt;">Avec la plupart des redoutables détails du JSOO maintenant expliqués, cet article montre comment créer les classes (constructeurs) d’objet “enfant” qui héritent des fonctionnalités de leur classes “parents”. De plus, nous présentons certains conseils sur où et comment utiliser le JSOO.</p> + </dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/JSON">Manipuler des données JSON</a></dt> + <dd> + <p style="margin-left: 36.0pt;">JavaScript Object Notation (JSON) est un format standard pour la représentation de données structurées comme les objets JavaScript, qui est communément utilisé pour représenter et transmettre les données sur les sites web (ex. : Envoyer certaines données du serveur au client, afin d’être affichées sur une page web). Vous le rencontrerez assez souvent. Aussi, dans cet article, nous vous donnons tout ce dont vous avez besoin pour travailler avec le format JSON utilisant le JavaScript, incluant l’accès aux éléments des données dans un objet JSON et l’écriture de votre propre JSON.</p> + </dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/Object_building_practice">Pratiques sur la construction d’objet</a></dt> + <dd> + <p style="margin-left: 36.0pt;">Dans l’article précédent nous avons fait le tour de l’essentiel de la théorie de l’objet JavaScript et les détails de sa syntaxe, vous donnant ainsi une solide base sur laquelle débuter. Dans cet article nous plongeons dans un exercice, vous donnant plus de pratique dans la construction d’objets JavaScript personnalisés, qui produisent quelque chose d’amusant et de plus coloré — quelques balles colorées et bondissantes.</p> + </dd> +</dl> + +<h2 id="Auto-évaluation">Auto-évaluation</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Ajoutez des fonctionnalités à notre démo des ballons bondissants</a></dt> + <dd>Dans cette évaluation, vous devrez utiliser la démo des balles bondissantes de l’article précédent comme un point de départ et y ajouter quelques nouvelles et intéressantes fonctionnalités.</dd> +</dl> + +<p>{{PreviousNext("Apprendre/JavaScript/Building_blocks", "JavaScript/Guide")}} </p> diff --git a/files/fr/learn/javascript/objects/js_orienté-objet/index.html b/files/fr/learn/javascript/objects/js_orienté-objet/index.html new file mode 100644 index 0000000000..c16e9a230e --- /dev/null +++ b/files/fr/learn/javascript/objects/js_orienté-objet/index.html @@ -0,0 +1,278 @@ +--- +title: Le JavaScript orienté objet pour débutants +slug: Learn/JavaScript/Objects/JS_orienté-objet +tags: + - Apprendre + - Débutant + - Guide + - JavaScript + - OOJS + - OOP + - POO +translation_of: Learn/JavaScript/Objects/Object-oriented_JS +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Après avoir parcouru les fondamentaux, nous allons aborder en détail le JavaScript orienté objet (JSOO). Cet article présente une approche simple de la programmation orientée objet (POO) et détaille comment JavaScript émule des classes objet au travers des méthodes constructeur et comment instancier ces objets.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td>Connaissances de base en informatique et compréhension des notions HTML et CSS, notions de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction</a>)</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre les concepts de base derrière la programmation orientée objet et comment ils s'appliquent à JavaScript ( « tout est objet » ) et comment créer des constructeurs et instancier des objets.</td> + </tr> + </tbody> +</table> + +<h2 id="La_programmation_orientée_objet_de_loin">La programmation orientée objet de loin</h2> + +<p>Pour commencer, donnons une vue simplifiée et de haut niveau de ce qu'est la programmation orientée objet (POO). On parle d'une vision simplifiée étant donnée que la POO peut devenir très vite complexe et qu'être exhaustif rendrait probablement la découverte plus confuse et difficile qu'autre chose. L'idée de base de la POO consiste à utiliser des objets pour modéliser les objets du monde réel que l'on souhaite représenter dans nos programmes et/ou de fournir un moyen simple d'accéder à une fonctionnalité qu'il serait difficile d'utiliser autrement.</p> + +<p>Les objets peuvent contenir des données et du code représentant de l'information au sujet de la chose que l'on essaie de modéliser ainsi que des fonctionnalités ou un comportement que l'on souhaite lui appliquer. Les données (et bien souvent les fonctions) associées à un objet peuvent être stockées (le terme officiel est <strong>encapsulé</strong>) à l'intérieur d'un paquet objet. Il est possible de donner un nom spécifique à un paquet objet afin d'y faire référence, on parle alors d'<strong>espace de noms</strong> ou <em>namespace</em>, il sera ainsi plus facile de le manipuler et d'y accéder. Les objets peuvent aussi servir pour stocker des données et les transférer facilement sur un réseau.</p> + +<h3 id="Définissons_un_modèle_objet">Définissons un modèle objet</h3> + +<p>Nous allons voir un programme simple qui affiche des informations à propos des élèves et des professeurs d'une école. Nous allons aborder la théorie de la programmation orientée objet de manière générale sans l'appliquer à un langage particulier.</p> + +<p>Pour débuter, nous pouvons réutiliser l'objet Personne que nous avons créé dans notre <a href="/fr/docs/Learn/JavaScript/Objects/Basics">premier article</a>, il définit un ensemble de données et actions d'une personne. Il existe tout un tas de choses que nous pourrions savoir au sujet d'une personne (son adresse, sa taille, sa pointure, son ADN, son numéro de passeport, ses traits particuliers significatifs… ). En l'occurrence, nous souhaitons uniquement afficher son nom, son âge, ses passions, écrire une petite introduction à son sujet en utilisant ces données et lui apprendre à se présenter. On parle alors d'<strong>abstraction </strong>: créer un modèle simplifié de quelque chose de complexe mais qui ne contient que les aspects qui nous intéressent. Il sera alors plus simple de manipuler ce modèle objet simplifié dans le cadre de notre programme.</p> + +<p><img alt="Classe Personne avec attributs élémentaires" src="https://mdn.mozillademos.org/files/14867/ClassePersonne.png" style="height: 216px; width: 604px;"></p> + +<p>Dans plusieurs langages de POO, la définition d'un objet est appelé une <strong>classe </strong>(comme on le verra ci-après, JavaScript se base sur un mécanisme et une terminologie différente). En réalité ce n'est pas vraiment un objet mais plutôt un modèle qui définit les propriétés que notre objet doit avoir.</p> + +<h3 id="Créons_des_objets">Créons des objets</h3> + +<p>À partir de notre classe, nous pouvons créer des objets, on parle alors d'<strong>instancier des objets</strong>, une classe objet a alors <strong>une instance</strong>. Il s'agit d'objets qui contiennent les données et attributs définis dans une classe. À partir de notre classe Personne, nous pouvons modéliser des personnes réelles :</p> + +<p><img alt="Instantiation on a Personn Class for JS examples (fr)" src="https://mdn.mozillademos.org/files/14869/InstancePersonne.png" style="height: 716px; width: 699px;"></p> + +<p>Lorsque l'instance d'un objet est créée, on appelle la <strong>fonction</strong> <strong>constructeur </strong>de la classe pour la créer. On parle d'<strong>instanciation</strong> d'un objet — l'objet ainsi créé est <strong>instancié</strong> à partir de la classe.</p> + +<h3 id="Classes_filles">Classes filles</h3> + +<p>Pour notre exemple, nous n'allons pas nous contenter de personnes génériques — nous pourrions utiliser des professeurs, des étudiants, qui sont des types un peu plus spécifiques de personnes. En POO, il est possible de créer de nouvelles classes à partir d'autres classes — ces <strong>classes filles</strong> nouvellement créées peuvent <strong>hériter</strong> des propriétés et des attributs de leur <strong>classe mère</strong>. Il est donc possible d'avoir des attributs partagés à l'ensemble des classes plutôt que de les dupliquer. Si besoin, il est possible d'ajouter des fonctions et attributs spécifiques sur chaque classe fille.</p> + +<p><img alt="Inheritance principle with French text for JS example" src="https://mdn.mozillademos.org/files/14887/HeritageClasse.PNG" style="height: 709px; width: 696px;"></p> + +<p>Cela s'avère très utile puisque les étudiants et les professeurs se ressemblent sur de nombreux aspects : ils ont un nom, un genre, un âge, il est donc utile de ne définir ces attributs qu'une seule fois. Il est aussi possible de redéfinir le même attribut dans différentes classes étant donné que l'attribut appartiendra à chaque fois à un nom d'espace différent. On pourra ainsi avoir différentes formes de salutations : « Hey, je m'appelle [prénom] » pour les étudiants ( « Hey je m'appelle Sam » ) tandis que les professeurs pourront dire quelque chose d'un peu plus formel comme « Bonjour, mon nom est [Titre][Nom] et j'enseigne [matière] » par exemple « Bonjour mon nom est M. Griffiths et j'enseigne la chimie ».</p> + +<div class="note"> +<p><strong>Note </strong>: On parle de <strong>polymorphisme</strong>, lorsque des objets réutilisent la même propriété, mais c'est juste pour info, vous embêtez pas.</p> +</div> + +<p>Une fois la classe fille créée il est alors possible de l'instancier et de créer des objets. Par exemple :</p> + +<p><img alt="Professor instantiation example for JS fr" src="https://mdn.mozillademos.org/files/14889/InstanceProf.png" style="height: 703px; width: 696px;"></p> + +<p>Dans la suite de l'article, nous nous intéresserons à la mise en œuvre de la programmation orientée objet (POO) au sein de JavaScript.</p> + +<h2 id="Constructeurs_et_instances_dobjet">Constructeurs et instances d'objet</h2> + +<p>Certains disent que le JavaScript n'est pas vraiment un langage de programmation orienté objet — Il n'existe pas, en JavaScript d'élément <code>class</code> pour créer des classes alors que c'est le cas dans plusieurs langages orientés objet. JavaScript quant à lui, utilise des fonctions spéciales appelées <strong>constructeurs</strong> pour définir les objets et leurs propriétés. Ces constructeurs s'avèrent utiles, puisque bien souvent, nous ne savons pas combien d'objets nous allons définir, les constructeurs nous permettent de créer autant d'objets que nécessaire et d'y associer des données et des fonctions au fur et à mesure.</p> + +<p>Lorsqu'un objet est instancié à partir d'une fonction constructeur, les fonctions de la classe ne sont pas copiées directement dans l'objet comme dans la plupart des langages orientés objet (OO). En JavaScript, les fonctions sont liées grâce à une chaîne de référence appelée chaîne prototype (voir <a href="/fr/docs/Learn/JavaScript/Objects/Object_prototypes">Prototypes Objet</a>). Il ne s'agit donc pas d'une véritable instanciation au sens strict puisque JavaScript utilise un mécanisme différent pour partager des fonctionnalités entre les objets.</p> + +<div class="note"> +<p><strong>Note</strong> : Ne pas être un "langage classique de POO" n'est pas nécessairement un défaut. Comme nous le mentionnions au début de l'article, la POO peut très vite devenir compliquée et JavaScript, grâce à ses différences parvient à utiliser certains concepts avancés tout en restant abordable.</p> +</div> + +<p>Voyons comment créer des classes via les constructeurs et les utiliser pour instancier des objets en JavaScript. Nous allons commencer par faire une copie locale du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a> que nous avons vu dans notre premier article sur les objets.</p> + +<h3 id="Un_exemple_simple">Un exemple simple</h3> + +<ol> + <li>Tout d'abord ; voyons comment définir une personne au travers d'une fonction classique. Vous pouvez ajouter l'exemple ci-dessous dans votre code existant : + <pre class="brush: js">function creerNouvellePersonne(nom) { + var obj = {}; + obj.nom = nom; + obj.salutation = function() { + alert('Salut ! Je m\'appelle ' + this.nom + '.'); + }; + return obj; +}</pre> + </li> + <li>Vous pouvez désormais créer une personne en appelant cette fonction, essayez en copiant les lignes suivantes dans la console JavaScript de votre navigateur : + <pre class="brush: js">var salva = creerNouvellePersonne('Salva'); +salva.nom; +salva.salutation();</pre> + Ça fonctionne bien, mais on peut améliorer notre exemple. Si l'on sait que l'on va créer un objet, pourquoi créer un objet vide pour l'utiliser ensuite ? Heureusement, JavaScript est là et possède des fonctions adaptées comme les constructeurs. À l'abordage !</li> + <li>Remplacez la fonction précédente par celle-ci : + <pre class="brush: js">function Personne(nom) { + this.nom = nom; + this.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + }; +}</pre> + </li> +</ol> + +<p>Le constructeur est l'équivalent JavaScript d'une classe. Il possède l'ensemble des fonctionnalités d'une fonction, cependant il ne renvoie rien et ne crée pas d'objet explicitement. Il se contente de définir les propriétés et les méthodes associées. Il y a aussi l'utilisation du mot-clé <code>this</code>, ce mot-clé sert au sein d'une instance qui sera créée à y faire référence, ainsi l'attribut nom sera, pour l'instance, égal au nom passé en argument de la fonction constructrice, la méthode <code>salutation</code><code>()</code> retournera elle aussi le nom passé en argument de la fonction constructrice.</p> + +<div class="note"> +<p><strong>Note </strong>: Les fonctions de type constructeur commencent généralement par une majuscule. Cette convention d'écriture permet de repérer les constructeurs plus facilement dans le code.</p> +</div> + +<p>Comment pouvons-nous utiliser un constructeur ?</p> + +<ol> + <li>Ajoutez les lignes suivantes au code déjà existant : + <pre class="brush: js">var personne1 = new Personne('Bob'); +var personne2 = new Personne('Sarah');</pre> + </li> + <li>Enregistrez votre code et relancez le dans votre navigateur puis essayez d'entrer les lignes suivantes dans la console : + <pre class="brush: js">personne1.nom +personne1.salutation() +personne2.nom +personne2.salutation()</pre> + </li> +</ol> + +<p>Pas mal ! Vous voyez désormais que nous avons deux nouveaux objets sur cette page, chaque objet étant stocké dans un espace de nom différent, pour y accéder il faut utiliser <code>personne1</code> et <code>personne2</code> pour préfixer les fonctions et attributs. Ce rangement permet de ne pas tout casser et de ne pas rentrer en collision avec d'autres fonctionnalités. Cependant les objets disposent du même attribut <code>nom</code> et de la même méthode <code>salutation()</code>. Heureusement, les attributs et les méthodes utilisent <code>this</code> ce qui leur permet d'utiliser les valeurs propres à chaque instance et de ne pas les mélanger.</p> + +<p>Revoyons l'appel au constructeur :</p> + +<pre class="brush: js">var personne1 = new Personne('Bob'); +var personne2 = new Personne('Sarah');</pre> + +<p>Dans chaque cas, le mot clé <code>new</code> est utilisé pour dire au navigateur que nous souhaitons définir une nouvelle instance, il est suivi du nom de la fonction que l'on utilise et de ses paramètres fournis entre parenthèses, le résultat est stocké dans une variable. Chaque instance est créée à partir de cette définition :</p> + +<pre class="brush: js">function Personne(nom) { + this.nom = nom; + this.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + }; +}</pre> + +<p>Une fois les objets créés, les variables <code>personne1</code> et <code>personne2</code> contiennent les objets suivants :</p> + +<pre class="brush: js">{ + nom: 'Bob', + salutation: function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + } +} + +{ + nom: 'Sarah', + salutation: function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + } +}</pre> + +<p>On peut remarquer qu'à chaque appel de notre fonction constructrice nous définissons <code>salutation()</code> à chaque fois. Cela peut être évité via la définition de la fonction au sein du prototype, ce que nous verrons plus tard.</p> + +<h3 id="Créons_une_version_finalisée_de_notre_constructeur">Créons une version finalisée de notre constructeur</h3> + +<p>L'exemple que nous avons utilisé jusqu'à présent était destiné à aborder les notions de base des constructeurs. Créons un constructeur digne de ce nom pour notre fonction constructrice <code>Personne()</code>.</p> + +<ol> + <li>Vous pouvez retirer le code que vous aviez ajouté précédemment pour le remplacer par le constructeur suivant, c'est la même fonction, ça reste un constructeur, nous avons juste ajouté quelques détails : + <pre class="brush: js">function Personne(prenom, nom, age, genre, interets) { + this.nom = { + prenom, + nom + }; + this.age = age; + this.genre = genre; + this.interets = interets; + this.bio = function() { + alert(this.nom.prenom + ' ' + this.nom.nom + ' a ' + this.age + ' ans. Il aime ' + this.interets[0] + ' et ' + this.interets[1] + '.'); + }; + this.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom.prenom + '.'); + }; +};</pre> + </li> + <li>Vous pouvez ajouter la ligne ci-dessous pour créer une instance à partir du constructeur : + <pre class="brush: js">var personne1 = new Personne('Bob', 'Smith', 32, 'homme', ['musique', 'ski']);</pre> + </li> +</ol> + +<p>Vous pouvez accéder aux fonctions des objets instanciés de la même manière qu'avant :</p> + +<pre class="brush: js">personne1['age'] +personne1.interets[1] +personne1.bio() +// etc.</pre> + +<div class="note"> +<p><strong>Note</strong> : Si vous avez du mal à faire fonctionner cet exemple, vous pouvez comparez votre travail avec notre version (voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html">oojs-class-finished.html</a> (vous pouvez aussi jeter un œil à la <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html">démo</a>)</p> +</div> + +<h3 id="Exercices">Exercices</h3> + +<p>Vous pouvez démarrer en instanciant de nouveaux objets puis en essayant de modifier et d'accéder à leurs attributs respectifs.</p> + +<p>D'autre part, il y a quelques améliorations possibles pour notre méthode <code>bio().</code> En effet elle affiche systématiquement le pronom 'il', même si votre personne est une femme ou bien préfère se définir par un autre genre. De plus, la biographie n'inclut que deux passions, même s'il y en a plus dans la liste. Essayez d'améliorer cette méthode. Vous pourrez mettre votre code à l'intérieur du constructeur (vous aurez probablement besoin de quelques structures conditionnelles et d'une boucle). Réflechissez à la syntaxe des phrases qui devra s'adapter en fonction du genre et du nombre de passions listées.</p> + +<div class="note"> +<p><strong>Note</strong>: Si vous êtes bloqués, nous avons mis une réponse possible sur notre dépôt <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">GitHub </a>(<a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">la démo</a>) —tentez d'abord l'aventure avant d'aller regarder la réponse !</p> +</div> + +<h2 id="Dautres_manières_dinstancier_des_objets">D'autres manières d'instancier des objets</h2> + +<p>Jusque là nous n'avons abordé que deux manières différentes pour créer une instance d'objet, la déclarer de manière explicite et en utilisant le constructeur.</p> + +<p>Elles sont toutes les deux valables, mais il en existe d'autres. Afin que vous les reconnaissiez lorsque vous vous baladez sur le Web, nous en avons listées quelques unes.</p> + +<h3 id="Le_constructeur_Object">Le constructeur Object()</h3> + +<p>Vous pouvez en premier lieu utiliser le constructeur <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object()</a></code> pour créer un nouvel objet. Oui, même les objets génériques ont leur propre constructeur, qui génère un objet vide.</p> + +<ol> + <li>Essayez la commande suivante dans la console JavaScript de votre navigateur : + <pre class="brush: js">var personne1 = new Object();</pre> + </li> + <li>On stocke ainsi un objet vide dans la variable personne1. Vous pouvez ensuite ajouter des attributs et des méthodes à cet objet en utilisant la notation point ou parenthèses comme vous le souhaitez. + <pre class="brush: js">personne1.nom = 'Chris'; +personne1['age'] = 38; +personne1.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); +};</pre> + </li> + <li>Vous pouvez aussi passer un objet en paramètre du constructeur <code>Object()</code>, afin de prédéfinir certains attributs et méthodes. + <pre class="brush: js">var personne1 = new Object({ + nom: 'Chris', + age: 38, + salutation: function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + } +});</pre> + </li> +</ol> + +<h3 id="Via_la_méthode_create">Via la méthode create()</h3> + +<p>Les constructeurs permettent de structurer le code : vous pouvez avoir l'ensemble de vos constructeurs au même endroit et ensuite créer les instances suivant vos besoins, en identifiant clairement leur origine. </p> + +<p>Cependant, on peut vouloir créér des instances d'un objet, sans forcément définir un constructeur au préalable. (Particulierement si l'on a peu d'instances de cet object). JavaScript intègre directement une méthode appelée <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> qui rend cela possible. Elle permet d'instancier un objet à partir d'un objet existant .</p> + +<ol> + <li>Essayez d'ajouter la ligne suivante dans votre console JavaScript : + <pre class="brush: js">var personne2 = Object.create(personne1);</pre> + </li> + <li>Maintenant : + <pre class="brush: js">personne2.nom +personne2.salutation()</pre> + </li> +</ol> + +<p><code>personne2</code> a été créée à partir de <code>personne1</code> — et elle possède les mêmes propriétés. </p> + +<p>L'inconvénient de <code>create()</code> est qu'elle n'est pas supportée par IE8. Ainsi, utiliser les constructeurs peut s'avérer plus judicieux lorsqu'il s'agit de supporter les anciens navigateurs Web.</p> + +<p>Nous verrons les détails et les effets de <code>create()</code> plus tard.</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Cet article vous a donné un aperçu simplifié de la programmation orientée objet. Tout n'y a pas été détaillé mais ça vous permet de vous faire une idée. Nous avons vu comment JavaScript s'appuyait sur un certain nombre de principes orienté objet tout en ayant un certain nombre de particularités. Nous avons aussi vu comment implémenter des classes en JavaScript via la fonction constructeur ainsi que les différentes manières de générer des instances d'objets.</p> + +<p>Dans le prochain article, nous explorerons le monde des objets prototypes en JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</p> diff --git a/files/fr/learn/javascript/objects/json/index.html b/files/fr/learn/javascript/objects/json/index.html new file mode 100644 index 0000000000..b06c79006d --- /dev/null +++ b/files/fr/learn/javascript/objects/json/index.html @@ -0,0 +1,338 @@ +--- +title: Manipuler des données JSON +slug: Learn/JavaScript/Objects/JSON +tags: + - Apprendre + - Article + - Débutant + - JSON + - JavaScript + - Manuel + - Objets + - Tutoriel +translation_of: Learn/JavaScript/Objects/JSON +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Le JavaScript Object Notation (JSON) est un format standard utilisé pour représenter des données structurées de façon semblable aux objets Javascript. Il est habituellement utilisé pour structurer et transmettre des données sur des sites web (par exemple, envoyer des données depuis un serveur vers un client afin de les afficher sur une page web ou vice versa). Comme cette notation est extrêmement courante, cet article a pour but de vous donner les connaissances nécessaires pour travailler avec JSON en JavaScript, vous apprendre à analyser la syntaxe du JSON afin d'en extraire des données et écrire vos propres objets JSON.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Vocabulaire de base d'informatique, connaissances de base en HTML et CSS, connaissances de base en JavaScript (voir <a href="/en-US/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Les blocs</a>) et en Javascript orienté objets (voir <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>).</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre comment utiliser les données stockées dans un objet JSON, et créer vos propres objets JSON.</td> + </tr> + </tbody> +</table> + +<h2 id="Plus_sérieusement_quest_ce_que_le_JSON">Plus sérieusement, qu'est ce que le JSON ?</h2> + +<p>{{glossary("JSON")}} est un format de données semblable à la syntaxe des objets JavaScript, qui a été popularisé par <a href="https://en.wikipedia.org/wiki/Douglas_Crockford">Douglas Crockford</a>. Malgré sa syntaxe très similaire à celle des objets littéraux JavaScript, JSON peut être utilisé indépendamment de ce langage et ainsi, de nombreux autres langages de programmation disposent de fonctionnalités permettant d'analyser la syntaxe du JSON et d'en générer.</p> + +<p>Le JSON se présente sous la forme d'une chaîne de caractères —utile lorsque vous souhaitez transmettre les données sur un réseau. Il a donc besoin d'être converti en un objet JavaScript natif lorsque vous souhaitez accéder aux données. Ce n'est pas vraiment un souci puisque le JavaScript fournit un objet global <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> disposant des méthodes pour assurer la conversion entre les deux.</p> + +<div class="note"> +<p><strong>Note </strong>: Convertir une chaîne de caractères en un objet natif se nomme <strong>analyse syntaxique (parsage)</strong> tandis que le contraire porte le nom de la <strong>linéarisation (stringification)</strong>.</p> +</div> + +<p>Un objet JSON peut être stocké dans son propre fichier qui se présente simplement sous la forme d'un fichier texte avec l'extension <code>.json</code> et le {{glossary("MIME type")}} <code>application/json</code>.</p> + +<h3 id="Structure_du_JSON">Structure du JSON</h3> + +<p>Nous disions tout à l'heure qu'un objet JSON n'était ni plus ni moins qu'un objet Javascript tout à fait normal et c'est généralement le cas. Un objet JSON accepte comme valeur les mêmes types de données de base que tout autre objet Javascript — chaînes de caractères, nombres, tableaux, booléens et tout autre objet littéral. Cela vous permet de hiérarchiser vos données comme ceci :</p> + +<pre class="brush: json">{ + "squadName": "Super hero squad", + "homeTown": "Metro City", + "formed": 2016, + "secretBase": "Super tower", + "active": true, + "members": [ + { + "name": "Molecule Man", + "age": 29, + "secretIdentity": "Dan Jukes", + "powers": [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name": "Madame Uppercut", + "age": 39, + "secretIdentity": "Jane Wilson", + "powers": [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + }, + { + "name": "Eternal Flame", + "age": 1000000, + "secretIdentity": "Unknown", + "powers": [ + "Immortality", + "Heat Immunity", + "Inferno", + "Teleportation", + "Interdimensional travel" + ] + } + ] +}</pre> + +<p>Si nous chargeons cet objet dans un fichier Javascript au sein d'une variable appelée <code>superHeroes</code> par exemple, nous pouvons accéder à ses données de la même façon que nous l'avons fait dans l'article <a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases de JavaScript orienté objets</a> à l'aide de la notation point / crochets. Par exemple :</p> + +<pre class="brush: js">superHeroes.hometown +superHeroes['active']</pre> + +<p>Pour accéder aux données plus profondes de la hiérarchie, vous n'avez qu'à enchaîner à la fois les noms des propriétés et les indexes des tableaux. Par exemple, l'expression suivante pointe vers le troisième superpouvoir du second super héros présent dans la liste :</p> + +<pre class="brush: js">superHeroes['members'][1]['powers'][2]</pre> + +<ol> + <li>D'abord, nous partons de la variable — <code>superHeroes</code></li> + <li>À l'intérieur de laquelle nous désirons accéder à la propriété <code>members</code>, donc, nous tapons <code>["members"]</code>.</li> + <li><code>members</code> contient un tableau renfermant des objets. Nous désirons accéder au second de ces objets, donc nous utilisons <code>[1]</code>.</li> + <li>À l'intérieur de cet objet, nous souhaitons accéder à la propriété <code>powers</code>, donc, nous utilisons <code>["powers"]</code>.</li> + <li>Enfin, à l'intérieur de cette propriété <code>powers</code> nous trouvons un nouveau tableau qui contient les super pouvoirs de ce héros. Nous désirons obtenir le troisième, donc nous tapons <code>[2]</code>.</li> +</ol> + +<div class="note"> +<p><strong>Note </strong>: L'objet JSON vu ci-dessus est disponible au sein d'une variable dans notre exemple <a href="http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html">JSONTest.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html">code source</a>). Essayez de le charger et d'accéder aux données en utilisant la console Javascript de votre navigateur.</p> +</div> + +<h3 id="Des_tableaux_en_tant_que_JSON">Des tableaux en tant que JSON</h3> + +<p>Un peu plus haut, nous avons dit qu'un objet JSON n'était ni plus ni moins qu'un objet Javascript tout à fait normal et c'est généralement le cas. La raison pour laquelle nous avons dit "généralement le cas" est qu'un tableau peut également être un objet JSON valide, par exemple :</p> + +<pre class="brush: json">[ + { + "name": "Molecule Man", + "age": 29, + "secretIdentity": "Dan Jukes", + "powers": [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name": "Madame Uppercut", + "age": 39, + "secretIdentity": "Jane Wilson", + "powers": [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + } +]</pre> + +<p>Le code ci dessus est une notation JSON parfaitement valide. Vous n'aurez qu'à accéder aux éléments de votre tableau en commençant avec un index, par exemple : <code>[0]["powers"][0]</code>.</p> + +<h3 id="Notes_diverses">Notes diverses</h3> + +<ul> + <li>Un objet JSON est uniquement un format de données — il ne contient que des propriétés mais pas de méthodes.</li> + <li>La notation JSON nécessite l'usage des guillemets pour être valide. Il est obligatoire d'utiliser des guillemets et non les apostrophes autour des chaînes de caractères et des noms de propriétés.</li> + <li>Une simple virgule ou un double point mal placé peut rendre votre fichier JSON invalide et non fonctionnel. Soyez très attentif aux données que vous utilisez (bien que le JSON généré automatiquement par un programme sera moins enclin à contenir des erreurs, à partir du moment où le programme est codé correctement). Vous pouvez utiliser une application comme <a href="http://jsonlint.com/">JSONLint</a> pour valider votre code JSON.</li> + <li>Dans l'absolu, le JSON peut prendre la forme de n'importe quel type de données qui serait valide pour être contenu dans du JSON et non juste des tableaux ou des objets. Ainsi, par exemple, une simple chaîne de caractères ou un nombre serait un objet JSON valide.</li> + <li>Contrairement au JavaScript dans lequel les propriétés (<em>keys</em>) non entourées de guillemets peuvent être utilisées, en JSON, seules les chaînes de caractères entourées de guillemets peuvent être utilisées en tant que propriétés.</li> +</ul> + +<h2 id="Activité_Manipuler_le_JSON_au_travers_dun_exemple">Activité : Manipuler le JSON au travers d'un exemple</h2> + +<p>Allez ! Un petit exemple pour voir comment nous pouvons nous servir de données JSON sur un site web.</p> + +<h3 id="Lançons_nous">Lançons nous</h3> + +<p>Pour commencer, faites une copie locale de nos fichiers <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html">heroes.html</a> et <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css">style.css</a>. Le dernier contient simplement quelques instructions CSS pour la mise en forme de notre page alors que le premier n'est ni plus ni moins qu'un squelette HTML de base :</p> + +<pre class="brush: html"><header> +</header> + +<section> +</section></pre> + +<p>Nous trouvons également un élément {{HTMLElement("script")}} dans lequel nous écrirons le code Javascript de cet exercice. Pour le moment, il ne contient que deux lignes destinées à récuperer les éléments {{HTMLElement("header")}} et {{HTMLElement("section")}} pour les stocker dans des variables :</p> + +<pre class="brush: js">var header = document.querySelector('header'); +var section = document.querySelector('section');</pre> + +<p>Nos données JSON sont disponibles sur notre GitHub ici : <a href="https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json</a>.</p> + +<p>Nous souhaitons les récupérer et, après quelques manipulations du DOM, les afficher comme ceci :</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13857/json-superheroes.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="Chargeons_notre_JSON">Chargeons notre JSON</h3> + +<p>Pour charger nos données JSON, nous allons utiliser l'API {{domxref("XMLHttpRequest")}} (qu'on appelle plus couramment <strong>XHR</strong>). Il s'agit d'un objet JavaScript extrêmement utile qui nous permet de construire une requête afin d'interroger un serveur pour obtenir des ressources diverses (images, texte, JSON, ou n'importe quel extrait HTML) le tout en Javascript. En d'autres termes, cela nous permet de mettre à jour de petites sections de contenu sans avoir à recharger notre page toute entière. Ceci conduit à des pages web plus réactives. Mais même si le sujet est très tentant, il dépasse largement l'objet de cet article pour être expliqué plus en détails.</p> + +<ol> + <li>Donc, pour commencer, nous allons charger l'URL du fichier JSON que nous voulons récupérer dans une variable. Aussi, ajouter la ligne suivante à votre code Javascript : + <pre class="brush: js">var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';</pre> + </li> + <li>Afin de créer une requête, nous avons besoin d'instancier un nouvel objet <code>XMLHttpRequest</code> à partir de son constructeur en utilisant le mot clé new. Ajouter la ligne suivante à votre script : + <pre class="brush: js">var request = new XMLHttpRequest();</pre> + </li> + <li>Maintenant, nous avons besoin d'ouvrir une nouvelle requête grâce à la méthode <code><a href="/en-US/docs/Web/API/XMLHttpRequest/open">open()</a></code>. Ajoutez la ligne suivante : + <pre class="brush: js">request.open('GET', requestURL);</pre> + + <p>Cette méthode prend au moins deux paramètres — il y a d'autres paramètres optionnels disponibles. Deux suffiront pour notre exemple :</p> + + <ul> + <li>La méthode HTTP à utiliser sur le réseau pour notre requête. Dans notre cas, la méthode <code><a href="/en-US/docs/Web/HTTP/Methods/GET">GET</a></code> est appropriée dans la mesure où nous voulons simplement récupérer quelques données.</li> + <li>L'URL où adresser notre requête — il s'agit de l'URL du fichier JSON dont nous parlions tout à l'heure.</li> + </ul> + </li> + <li>Ensuite, ajoutez les deux lignes suivantes — ici, nous attribuons la valeur <code>'json'</code><strong> </strong>à <code><a href="/en-US/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code>, signalant ainsi au serveur que nous attendons une réponse au format JSON. Puis, nous envoyons notre requête à l'aide de la méthode <code><a href="/en-US/docs/Web/API/XMLHttpRequest/send">send()</a></code> : + <pre class="brush: js">request.responseType = 'json'; +request.send();</pre> + </li> + <li>La dernière partie de cette section concerne la réponse du serveur et son traitement. Ajoutez les lignes suivantes à la fin de votre code : + <pre class="brush: js">request.onload = function() { + var superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + </li> +</ol> + +<p>Ici, nous stockons la réponse à notre requête (disponible au travers de la propriété <code><a href="/en-US/docs/Web/API/XMLHttpRequest/response">response</a></code>) dans la variable <code>superHeroes</code> ; cette variable contiendra désormais l'objet JavaScript basé sur le JSON ! Nous passerons ensuite cet objet en paramètre à deux fonctions — la première remplira le <<code>header></code> avec les données correspondantes tandis que la seconde créera une carte d'identité pour chaque héros de l'équipe et l'ajoutera dans la <code><section></code>.</p> + +<p>Nous avons encapsulé ce code dans un gestionnaire d'évènements qui s'exécutera quand l'évènement load sera déclenché sur l'objet request (voir <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) — simplement parce que l'évènement load est déclenché quand une réponse a été renvoyée avec succès ; en procédant de la sorte, nous serons certains que la propriété <code>request.response</code> sera disponible au moment où nous essayerons d'en faire quelque chose.</p> + +<h3 id="Remplissage_de_len-tête">Remplissage de l'en-tête</h3> + +<p>Maintenant que nous avons récupéré et converti en objet JavaScript nos données JSON, il est temps d'en faire bon usage : implémentons donc les deux fonctions évoquées ci-dessus. Avant tout, ajoutons les lignes suivantes en dessous de notre code :</p> + +<pre class="brush: js">function populateHeader(jsonObj) { + var myH1 = document.createElement('h1'); + myH1.textContent = jsonObj['squadName']; + header.appendChild(myH1); + + var myPara = document.createElement('p'); + myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + jsonObj['formed']; + header.appendChild(myPara); +}</pre> + +<p>Nous avons appelé le paramètre de cette fonction <code>jsonObj</code> afin de garder en tête que cet objet JavaScript provient du JSON. Ici, nous créons tout d'abord un élément {{HTMLElement("h1")}} à l'aide de <code><a href="/en-US/docs/Web/API/Document/createElement">createElement()</a></code>, nous fixons son <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> à la valeur de la propriété <code>squadName</code> de l'objet, puis nous l'ajoutons à l'en-tête en utilisant <code><a href="/en-US/docs/Web/API/Node/appendChild">appendChild()</a></code>. Ensuite, nous faisons quelque chose de relativement similaire avec un élément paragraphe : nous le créons, fixons son contenu et l'ajoutons à l'en-tête. La seule différence est que pour son contenu, nous avons concaténé la chaîne de caractère <code>homeTown</code> et la propriété <code>formed</code> de l'objet.</p> + +<h3 id="Création_des_fiches_des_héros">Création des fiches des héros</h3> + +<p>Maintenant, ajoutons la fonction suivante qui crée et affiche les fiches de nos super-héros en dessous de notre code :</p> + +<pre class="brush: js">function showHeroes(jsonObj) { + var heroes = jsonObj['members']; + + for (var i = 0; i < heroes.length; i++) { + var myArticle = document.createElement('article'); + var myH2 = document.createElement('h2'); + var myPara1 = document.createElement('p'); + var myPara2 = document.createElement('p'); + var myPara3 = document.createElement('p'); + var myList = document.createElement('ul'); + + myH2.textContent = heroes[i].name; + myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity; + myPara2.textContent = 'Age: ' + heroes[i].age; + myPara3.textContent = 'Superpowers:'; + + var superPowers = heroes[i].powers; + for (var j = 0; j < superPowers.length; j++) { + var listItem = document.createElement('li'); + listItem.textContent = superPowers[j]; + myList.appendChild(listItem); + } + + myArticle.appendChild(myH2); + myArticle.appendChild(myPara1); + myArticle.appendChild(myPara2); + myArticle.appendChild(myPara3); + myArticle.appendChild(myList); + + section.appendChild(myArticle); + } +}</pre> + +<p>Pour commencer, on stocke la propriété <code>members</code> de l'objet JavaScript dans une nouvelle variable. Ce tableau contient plusieurs objets contenant les informations relatives à chaque héros.</p> + +<p>Maintenant, on utilise une <a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code">boucle for</a> pour parcourir chaque object du tableau. Pour chaque cas, il faut :</p> + +<ol> + <li>Créer plusieurs nouveaux éléments : un <code><article></code>, un <code><h2></code>, trois <code><p></code>s, et un <code><ul></code>.</li> + <li>Mettre le <code>name</code> du héros actuel dans le <code><h2></code>.</li> + <li>Remplir les trois paragraphes avec leur <code>secretIdentity</code>, leur <code>age</code>, et une ligne nommée "Superpowers:" pour présenter la liste des super-pouvoirs.</li> + <li>Stocker la propriété <code>powers</code> dans une nouvelle variable nommée <code>superPowers</code> contenant un tableau listant les super-pouvoirs du héros actuel.</li> + <li>Utiliser une autre boucle <code>for</code> pour parcourir les super-pouvoirs du héros actuel — créer pour chacun d'entre eux un élément <code><li></code>, y placer le super-pouvoir et placer le <code>listItem</code> dans l'élément <code><ul></code> (<code>myList</code>) en utilisant <code>appendChild()</code>.</li> + <li>Pour finir, on ajoute <code><h2></code>, les <code><p></code>s et <code><ul></code> à <code><article></code> (<code>myArticle</code>), et on ajoute <code><article></code> à <code><section></code>. L'ordre d'ajout est important, c'est l'ordre dans lequel les éléments seront affichés dans le HTML.</li> +</ol> + +<div class="note"> +<p><strong>Note </strong>: Si vous ne parvenez pas à faire fonctionner l'exemple, consultez notre code source <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html">heroes-finished.html</a> (ou regardez-le <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html">en action</a>.)</p> +</div> + +<div class="note"> +<p><strong>Note </strong>: Si vous comprenez difficilement la notation avec un point/une accolade utilisée pour accéder au JSON, ouvrez le fichier <a href="http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">superheroes.json</a> dans un nouvel onglet ou dans votre éditeur de texte et consultez-le pendant la lecture de notre code Javascript. Vous pouvez également vous reporter à notre article <a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases du JavaScript orienté objet</a> pour obtenir plus de détails sur la notation avec un point et avec une accolade.</p> +</div> + +<h2 id="Conversion_entre_objets_et_textes">Conversion entre objets et textes</h2> + +<p>Dans l'exemple ci-dessus, accéder au JSON est simple, il suffit de définir la requête XHR pour renvoyer la réponse au format JSON en écrivant :</p> + +<pre class="brush: js">request.responseType = 'json';</pre> + +<p>Mais on n'a pas toujours cette chance — il est possible de recevoir la réponse JSON sous la forme d'une chaîne de caractères et il faut alors la convertir en objet. À l'inverse, lorsqu'on veut envoyer un objet JavaScript à travers le réseau il faut au préalable le convertir en JSON (une chaîne de caractères). Heureusement, ces deux problèmes sont tellement communs dans le développement web qu'un objet <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/JSON">JSON</a> interne a été ajouté aux navigateurs depuis longtemps, contenant les deux méthodes suivantes :</p> + +<ul> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">parse()</a></code> qui accepte un objet JSON sous la forme d'une chaîne de caractères en paramètre et renvoie l'objet JavaScript correspondant.</li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringify()</a></code> qui accepte un objet JavaScript en paramètre et renvoie son équivalent sous la forme d'une chaîne de caractères JSON.</li> +</ul> + +<p>Vous pouvez voir la première méthode en action dans notre exemple <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html">heroes-finished-json-parse.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html">code source</a>) — C'est la même chose que pour l'exemple que nous avons écrit un peu plus tôt, à ceci près qu'on indique à la requête XHR de renvoyer la réponse en JSON sous forme de texte avant d'utiliser la méthode <code>parse()</code> pour la convertir en objet JavaScript. La partie du code correspondante se trouve ci-dessous :</p> + +<pre class="brush: js">request.open('GET', requestURL); +request.responseType = 'text'; // now we're getting a string! +request.send(); + +request.onload = function() { + var superHeroesText = request.response; // get the string from the response + var superHeroes = JSON.parse(superHeroesText); // convert it to an object + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + +<p>Comme vous pouvez le deviner, <code>stringify()</code> fait exactement le contraire. Essayez d'entrer les lignes ci-dessous une par une dans la console Javascript de votre navigateur pour voir la méthode en action :</p> + +<pre class="brush: js">var myJSON = { "name": "Chris", "age": "38" }; +myJSON +var myString = JSON.stringify(myJSON); +myString</pre> + +<p>On commence par créer un objet JavaScript puis on vérifie son contenu avant de le convertir en chaîne de caractères JSON avec <code>stringify()</code> — en sauvegardant au passage le résultat dans une nouvelle variable avant d'effectuer à nouveau une vérification du contenu.</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Dans cet article, nous vous donnons un manuel simple pour utiliser le JSON dans vos programmes, incluant les méthodes de création et d'analyse syntaxique (parsage) du JSON et d'accès aux données qu'il contient. Dans le prochain article, nous débuterons l'apprentissage du Javascript orienté objet.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">La page de référence sur l'objet JSON</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest">La page de référence sur l'objet XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Utiliser XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/HTTP/Methods">Les méthodes de requêtes HTTP </a></li> + <li><a href="http://json.org">Le site web officiel avec un lien vers les normes de l' ECMA</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</p> diff --git a/files/fr/learn/javascript/objects/la_construction_d_objet_en_pratique/index.html b/files/fr/learn/javascript/objects/la_construction_d_objet_en_pratique/index.html new file mode 100644 index 0000000000..a2ab4270eb --- /dev/null +++ b/files/fr/learn/javascript/objects/la_construction_d_objet_en_pratique/index.html @@ -0,0 +1,316 @@ +--- +title: La construction d'objet en pratique +slug: Learn/JavaScript/Objects/la_construction_d_objet_en_pratique +tags: + - Apprendre + - Article + - Canvas + - Débutant + - JavaScript + - Manuel + - Objets + - Tutoriel +translation_of: Learn/JavaScript/Objects/Object_building_practice +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Dans l'article précédent, nous avons passé en revue l'essentiel de la théorie de l'objet Javascript et sa syntaxe détaillée, vous donnant ainsi des bases solides sur lesquelles commencer. Dans le présent article nous plongeons dans un exercice pratique afin d'accroître votre savoir-faire dans la construction d'objets entièrement personnalisés donnant un résultat plutôt amusant et très coloré.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td> + <p>Connaissance basique de l'informatique, une compréhension basique du HTML et du CSS, une familiarité avec les bases du JavaScript (voir <a href="/en-US/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Les blocs de construction</a>) et les bases de la programmation objet en JavaScript (voir <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>). </p> + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + <p>Acquérir plus de pratique dans l'utilisation des objets et des techniques orientées objet dans un contexte "monde réel".</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Faisons_bondir_quelques_balles">Faisons bondir quelques balles</h2> + +<p>Dans cet article, nous écrirons une démo classique de "balles bondissantes", pour vous montrer à quel point les objets peuvent être utiles en JavaScript. Nos petites balles bondiront partout sur notre écran et changeront de couleurs lorsqu'elles se toucheront. L'exemple finalisé ressemblera un peu à ceci : </p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13865/bouncing-balls.png" style="display: block; height: 614px; margin: 0px auto; width: 800px;"></p> + +<ol> +</ol> + +<p>Cet exemple utilise l'<a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">API Canvas </a> pour dessiner les balles sur l'écran, et l'API <a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> pour animer l'ensemble de l'affichage — Nul besoin d'avoir une connaissance préalable de ces APIs, nous expérons qu'une fois cet article terminé, vous aurez envie d'en faire une exploration approfondie. Tout le long du parcours nous utiliserons certains objets formidables et vous montrerons nombre de techniques sympathiques comme des balles bondissantes sur les murs et la vérification de balles qui s'entrechoquent (encore connue sous l'appelation <strong>détection de collision</strong>).</p> + +<p>Pour commencer, faites des copies locales de nos fichiers <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index.html">index.html</a></code>, <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a></code>, et <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main.js">main.js</a></code>. Ces fichiers contiennent respectivement :</p> + +<ol> + <li>Un document HTML très simple contenant un élément {{HTMLElement("h1")}} , un élément {{HTMLElement("canvas")}} pour dessiner nos balles dessus et des élements pour appliquer notre CSS et notre JavaScript à notre HTML ;</li> + <li>Quelques styles très simples qui servent principalement à mettre en forme et placer le <code><h1></code>, et se débarasser de toutes barres de défilement ou de marges autour du pourtour de notre page (afin que cela paraisse plus sympathique et élégant) ;</li> + <li>Un peu de JavaScript qui sert à paramétrer l'élément <code><canvas></code> et fournir les fonctions globalles que nous utiliserons.</li> +</ol> + +<p>La première partie du script ressemble à ceci :</p> + +<pre class="brush: js">const canvas = document.querySelector('canvas'); + +const ctx = canvas.getContext('2d'); + +const width = canvas.width = window.innerWidth; +const height = canvas.height = window.innerHeight;</pre> + +<p>Ce script prend une référence à l'élément <code><canvas></code> et ensuite invoque la méthode <code><a href="/en-US/docs/Web/API/HTMLCanvasElement/getContext">getContext()</a></code> sur lui, nous donnant ainsi un contexte sur lequel nous pouvons commencer à dessiner. La variable résultante (<code>ctx</code>) est l'objet qui représente directement la surface du Canvas où nous pouvons dessiner et qui nous permet de dessiner des formes 2D sur ce dernier. </p> + +<p>Après, nous configurons les variables <code>width</code> (largeur) et <code>height</code>(hauteur), et la largeur et la hauteur de l'élément canvas (représentés par les propriétés <code>canvas.width</code> et <code>canvas.height</code> ) afin qu'elles soient identiques à la fenêtre du navigateur (la surface sur laquelle apparaît la page web— Ceci peut être tiré des propriétés {{domxref("Window.innerWidth")}} et {{domxref("Window.innerHeight")}}).</p> + +<p>Vous verrez qu'ici nous enchaînons les assignations des valeurs des différentes variables ensemble à des fins de rapidité. Ceci est parfaitement autorisé.</p> + +<p>Le dernier morceau du script ressemble à ceci :</p> + +<pre class="brush: js">function random(min, max) { + var num = Math.floor(Math.random() * (max - min + 1)) + min; + return num; +}</pre> + +<p>Cette fonction prend deux nombres comme arguments, et renvoie un nombre compris entre les deux. </p> + +<h2 id="Modéliser_une_balle_dans_notre_programme">Modéliser une balle dans notre programme</h2> + +<p>Notre programme met en œuvre beaucoup de balles bondissant partout sur l'écran. Comme nos balles se comporteront toutes de la même façon, cela semble tout à fait sensé de les représenter avec un objet. Commençons donc en ajoutant le constructeur suivant à la fin de notre code.</p> + +<pre class="brush: js">function Ball(x, y, velX, velY, color, size) { + this.x = x; + this.y = y; + this.velX = velX; + this.velY = velY; + this.color = color; + this.size = size; +}</pre> + +<p>Ici, nous incluons des paramètres qui définissent des propriétés dont chaque balle aura besoin pour fonctionner dans notre programme :</p> + +<ul> + <li>Les coordonnées <code>x</code> et <code>y</code> — les coordonnées verticales et horizontales où la balle débutera sur l'écran. Ceci peut se trouver entre 0 (coin à gauche en haut) et la valeur de la hauteur et de la largeur de la fenêtre du navigateur (coin en bas à droite).</li> + <li>Une vitesse horizontale et verticale (<code>velX</code> et <code>velY</code>) — à chaque balle est attribuée une vitesse horizontale et verticale; en termes réels ces valeurs seront régulièrement ajoutéés aux valeurs de la coordonnée <code>x</code>/<code>y</code> quand nous commencerons à animer les balles, afin de les faire bouger d'autant sur chaque vignette (frame).</li> + <li><code>color</code> — chaque balle a une couleur.</li> + <li><code>size</code> — chaque balle a une taille — ce sera son rayon mesuré en pixels.</li> +</ul> + +<p>Ceci règle le problème des propriétés mais qu'en est il des méthodes ? Nous voulons maintenant amener nos balles à faire quelque chose dans notre programme.</p> + +<h3 id="Dessiner_la_balle">Dessiner la balle</h3> + +<p>En premier lieu ajoutez la méthode <code>draw()</code> au <code>prototype</code> de <code>Ball()</code> :</p> + +<pre class="brush: js">Ball.prototype.draw = function() { + ctx.beginPath(); + ctx.fillStyle = this.color; + ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); + ctx.fill(); +}</pre> + +<p>En utilisant cette fonction, nous pouvons dire à notre balle de se dessiner sur l'écran en appelant une série de membres du contexte 2D du canvas que nous avons défini plus tôt (<code>ctx</code>). Le contexte est comme le papier et maintenant nous allons demander à notre stylo d'y dessiner quelque chose :</p> + +<ul> + <li>Premièrement, nous utilisons <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> pour spécifier que nous voulons dessiner une forme sur le papier.</li> + <li>Ensuite, nous utilisons <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> pour définir de quelle couleur nous voulons que la forme soit — nous lui attribuons la valeur de la propriété <code>color</code> de notre balle.</li> + <li>Après, nous utilisons la méthode <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/arc">arc()</a></code> pour tracer une forme en arc sur le papier. Ses paramètres sont : + <ul> + <li>Les positions <code>x</code> et <code>y</code> du centre de l'arc — nous specifions donc les propriétés <code>x</code> et <code>y </code>de notre balle.</li> + <li>Le rayon de l'arc — nous specifions la propriété <code>size</code> de notre balle.</li> + <li>Les deux derniers paramètres spécifient l'intervalle de début et de fin en degrés pour dessiner l'arc. Ici nous avons spécifié 0 degrés et <code>2 * PI </code>qui est l'équivalent de 360 degrés en radians (malheureusement vous êtes obligés de spécifier ces valeurs en radians et non en degrés). Cela nous donne un cercle complet. Si vous aviez spécifié seulement <code>1 * PI</code>, vous auriez eu un demi-cercle (180 degrés).</li> + </ul> + </li> + <li>En dernière position nous utilisons la méthode <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> qui est habituellement utilisée pour spécifier que nous souhaitons mettre fin au dessin que nous avons commencé avec <code>beginPath()</code>, et remplir la surface délimitée avec la couleur que nous avions spécifiée plus tôt avec <code>fillStyle</code>.</li> +</ul> + +<p>Vous pouvez déjà commencer à tester votre objet.</p> + +<ol> + <li>Sauvegardez le code et chargez le fichier html dans un navigateur.</li> + <li>Ouvrez la console JavaScript du navigateur et actualisez la page afin que la taille du canvas change et prenne la petite taille restante de la fenêtre lorsque la console est ouverte.</li> + <li>Tapez dans la console ce qui suit afin de créer une nouvelle instance de balle : + <pre class="brush: js">let testBall = new Ball(50, 100, 4, 4, 'blue', 10);</pre> + </li> + <li>Essayez d'appeler ses membres : + <pre class="brush: js">testBall.x +testBall.size +testBall.color +testBall.draw()</pre> + </li> + <li>Lorsque vous entrerez la dernière ligne, vous devriez voir la balle se dessiner quelque part sur votre canvas.</li> +</ol> + +<h3 id="Mettre_à_jour_les_données_de_la_balle">Mettre à jour les données de la balle</h3> + +<p>Nous pouvons dessiner la balle dans n'importe quelle position, mais actuellement pour commencer à la bouger nous aurons besoin d'une sorte de fonction de mise à jour. Insérez donc le code suivant à la fin de votre fichier JavaScript pour ajouter une méthode <code>update()</code> au <code>prototype</code> de <code>Ball()</code>:</p> + +<pre class="brush: js">Ball.prototype.update = function() { + if ((this.x + this.size) >= width) { + this.velX = -(this.velX); + } + + if ((this.x - this.size) <= 0) { + this.velX = -(this.velX); + } + + if ((this.y + this.size) >= height) { + this.velY = -(this.velY); + } + + if ((this.y - this.size) <= 0) { + this.velY = -(this.velY); + } + + this.x += this.velX; + this.y += this.velY; +}</pre> + +<p>Les quatre premières parties de la fonction vérifient si la balle a atteint le rebord du canvas. Si c'est le cas, nous inversons la polarité de la vitesse appropriée pour faire bouger la balle dans le sens opposé. Donc par exemple, si la balle se déplaçait vers le haut (positif <code>velY</code>) alors la vitesse verticale est changée afin qu'elle commence à bouger plutôt vers le bas (negatif <code>velY</code>).</p> + +<p>Dans les quatre cas nous :</p> + +<ul> + <li>Verifions si la coordonnée <code>x</code> est plus grande que la largeur du canvas (la balle est en train de sortir du côté droit).</li> + <li>Verifions si la coordonnée <code>x</code> est plus petite que 0 (la balle est en train de sortir du côté gauche).</li> + <li>Verifions si la coordonnée <code>y</code> est plus grande que la hauteur du canvas (la balle est en train de sortir par le bas).</li> + <li>Verifions si la coordonnée <code>y</code> est plus petite que 0 (la balle est en train de sortir par le haut).</li> +</ul> + +<p>Dans chaque cas, nous incluons la taille <code>size</code> de la balle dans les calculs parce que les coordonnées <code>x</code>/<code>y</code> sont situées au centre de la balle mais nous voulons que le pourtour de la balle rebondisse sur le rebord — nous ne voulons pas que la balle sorte à moité hors de l'écran avant de commencer à rebondir vers l'arrière.</p> + +<p>Les deux dernières lignes ajoutent la valeur <code>velX</code> à la coordonnée <code>x</code> et la valeur <code>velY</code> à la coordonnée <code>y</code> — la balle est en effet mise en mouvement chaque fois que cette méthode est invoquée.</p> + +<p><span class="short_text" id="result_box" lang="fr"><span>Cela suffira pour l'instant,</span> <span>passons à l'animation !</span></span></p> + +<h2 id="Animer_la_balle">Animer la balle</h2> + +<p><span id="result_box" lang="fr"><span>Maintenant, rendons cela amusant.</span> <span>Nous allons commencer à ajouter des balles au canvas et à les animer.</span></span></p> + +<ol> + <li><span id="result_box" lang="fr"><span>Tout d'abord, nous avons besoin d'un endroit où stocker toutes nos balles.</span> <span>Le tableau suivant fera ce travail </span></span>— <span lang="fr"><span>ajoutez-le au bas de votre code maintenant :</span></span> + + <pre class="brush: js">let balls = []; +</pre> + + <pre>while (balls.length < 25) { + let size = random(10,20); + let ball = new Ball( + // ball position always drawn at least one ball width + // away from the edge of the canvas, to avoid drawing errors + random(0 + size,width - size), + random(0 + size,height - size), + random(-7,7), + random(-7,7), + 'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')', + size + ); + + balls.push(ball); +}</pre> + <span>Tous les programmes qui animent les choses impliquent généralement une boucle d'animation, qui sert à mettre à jour les informations dans le programme et à restituer ensuite la vue résultante sur chaque image de l'animation.</span> <span>C'est la base de la plupart des jeux et autres programmes similaires.</span></li> + <li><span id="result_box" lang="fr"><span>Ajoutez ce qui suit au bas de votre code maintenant :</span></span> + <pre class="brush: js">function loop() { + ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; + ctx.fillRect(0, 0, width, height); + + for (let i = 0; i < balls.length; i++) { + balls[i].draw(); + balls[i].update(); + } + + requestAnimationFrame(loop); +}</pre> + + <p>Notre fonction <code>loop()</code> fonctionne comme suit :</p> + + <ul> + <li><span id="result_box" lang="fr"><span>On définit la couleur de remplissage du canvas en noir semi-transparent, puis dessine un rectangle de couleur sur toute la largeur et la hauteur du canvas, en utilisant <code>fillRect()</code> (les quatre paramètres fournissent une coordonnée de départ et une largeur et une hauteur pour le rectangle dessiné</span> <span>).</span> <span>Cela sert à masquer le dessin de l'image précédente avant que la suivante ne soit dessinée.</span> <span>Si vous ne faites pas cela, vous verrez juste de longs serpents se faufiler autour de la toile au lieu de balles qui bougent !</span> <span>La couleur du remplissage est définie sur semi-transparent, <code>rgba (0,0,0,.25)</code>, pour permettre aux quelques images précédentes de briller légèrement, produisant les petites traînées derrière les balles lorsqu'elles se déplacent.</span> <span>Si vous avez changé 0.25 à 1, vous ne les verrez plus du tout.</span> <span>Essayez de faire varier ce dernier nombre (entre 0 et 1) pour voir l'effet qu'il a.</span></span></li> + <li><span id="result_box" lang="fr"><span>On crée un nouvel objet <code>Ball()</code> avec des attributs générées aléatoirement grâce à la fonction <code>random()</code>, puis on ajoute l'objet au tableau, mais seulement lorsque le nombre de balles dans le tableau est inférieur à 25. Donc</span> <span>quand on a 25 balles à l'écran, plus aucune balle supplémentaire n'apparaît.</span> <span>Vous pouvez essayer de faire varier le nombre dans <code>balls.length <25</code> pour obtenir plus, ou moins de balles à l'écran.</span> <span>En fonction de la puissance de traitement de votre ordinateur / navigateur, spécifier plusieurs milliers de boules peut ralentir l'animation de façon très significative !</span></span></li> + <li><span id="result_box" lang="fr"><span>Le programme boucle à travers tous les objets du tableau sur chacun desquels il exécute la fonction <code>draw()</code> et <code>update()</code> pour dessiner à l'écran chaque balle et faire les mise à jour de chaque attribut vant le prochain rafraîchissement.</span></span></li> + <li><span id="result_box" lang="fr"><span>Exécute à nouveau la fonction à l'aide de la méthode <code>requestAnimationFrame()</code> </span></span>—<span lang="fr"><span> lorsque cette méthode est exécutée en permanence et a reçu le même nom de fonction, elle exécute cette fonction un nombre défini de fois par seconde pour créer une animation fluide.</span> <span>Cela se fait généralement de manière récursive </span></span>—<span lang="fr"><span> ce qui signifie que la fonction s'appelle elle-même à chaque fois qu'elle s'exécute, de sorte qu'elle sera répétée encore et encore.</span></span></li> + </ul> + </li> + <li>Finallement mais non moins important, ajoutez la ligne suivante au bas de votre code — nous devons appeler la fonction une fois pour démarrer l'animation. + <pre class="brush: js">loop();</pre> + </li> +</ol> + +<p>Voilà pour les bases — <span id="result_box" lang="fr"><span>essayez d'enregistrer et de rafraîchir pour tester vos balles bondissantes!</span></span></p> + +<h2 id="Ajouter_la_détection_de_collision">Ajouter la détection de collision</h2> + +<p><span id="result_box" lang="fr"><span>Maintenant, pour un peu de plaisir, ajoutons une détection de collision à notre programme, afin que nos balles sachent quand elles ont frappé une autre balle.</span></span></p> + +<ol> + <li><span id="result_box" lang="fr"><span>Tout d'abord, ajoutez la définition de méthode suivante ci-dessous où vous avez défini la méthode <code>update()</code> (c'est-à-dire le bloc <code>Ball.prototype.update</code>).</span></span> + + <pre class="brush: js">Ball.prototype.collisionDetect = function() { + for (let j = 0; j < balls.length; j++) { + if (!(this === balls[j])) { + const dx = this.x - balls[j].x; + const dy = this.y - balls[j].y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < this.size + balls[j].size) { + balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; + } + } + } +}</pre> + + <p><span id="result_box" lang="fr"><span>Cette méthode est un peu complexe, donc ne vous inquiétez pas si vous ne comprenez pas exactement comment cela fonctionne pour le moment.</span> Regardons cela pas-à-pas<span> :</span></span></p> + + <ul> + <li><span id="result_box" lang="fr"><span>Pour chaque balle <em>b</em>, nous devons vérifier chaque autre balle pour voir si elle est entrée en collision avec <em>b</em>.</span> <span>Pour ce faire, on inspecte toutes les balles du tableau</span></span> <code>balls[]</code> dans une boucle <code>for</code>.</li> + <li><span id="result_box" lang="fr"><span>Immédiatement à l'intérieur de cette boucle <code>for</code>, une instruction <code>if</code> vérifie si la balle courante <em>b'</em> , inspectée dans la boucle, n'est égale à la balle <em>b. Le code correspondant est : </em><code><em>b</em>'!== <em>b</em></code></span></span><span lang="fr"><span><em>. </em>En effet,</span> n<span>ous ne voulons pas vérifier si une balle <em>b</em> est entrée en collision avec elle-même !</span> N<span>ous contrôlons donc si la balle actuelle <em>b</em></span></span>—<span lang="fr"><span>dont la méthode <code>collisionDetect()</code> est invoquée</span></span>—<span lang="fr"><span>est distincte de la balle <em>b' </em>inspectée dans la boucle<em>. </em>Ainsi</span> <span>le bloc de code venant après l'instruction <code>if</code> ne s'exécutera que si les balles <em>b</em> et <em>b'</em> ne sont pas identiques.</span></span></li> + <li><span id="result_box" lang="fr"><span>Un algorithme classique permet ensuite de vérifier la superposition de deux disques</span><span>.</span> <span>Ceci est expliqué plus loin dans</span></span> <a href="/en-US/docs/Games/Techniques/2D_collision_detection">2D collision detection</a>.</li> + <li><span id="result_box" lang="fr"><span>Si une collision est détectée, le code à l'intérieur de l'instruction interne <code>if</code> est exécuté.</span> <span>Dans ce cas, nous définissons simplement la propriété <code>color</code> des deux cercles à une nouvelle couleur aléatoire.</span> <span>Nous aurions pu faire quelque chose de bien plus complexe, comme faire rebondir les balles de façon réaliste, mais cela aurait été beaucoup plus complexe à mettre en œuvre.</span> <span>Pour de telles simulations de physique, les développeurs ont tendance à utiliser des bibliothèques de jeux ou de physiques telles que</span></span> <a href="http://wellcaffeinated.net/PhysicsJS/">PhysicsJS</a>, <a href="http://brm.io/matter-js/">matter.js</a>, <a href="http://phaser.io/">Phaser</a>, etc.</li> + </ul> + </li> + <li><span id="result_box" lang="fr"><span>Vous devez également appeler cette méthode dans chaque image de l'animation.</span> <span>Ajouter le code ci-dessous</span></span> juste après la ligne <code>balls[i].update();</code>: + <pre class="brush: js">balls[i].collisionDetect();</pre> + </li> + <li><span id="result_box" lang="fr"><span>Enregistrez et rafraîchissez la démo à nouveau, et vous verrez vos balles changer de couleur quand elles entrent en collision !</span></span></li> +</ol> + +<div class="note"> +<p><strong>Note </strong>: <span id="result_box" lang="fr"><span>Si vous avez des difficultés à faire fonctionner cet exemple, essayez de comparer votre code JavaScript avec notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">version finale</a> (voir également la <a href="http://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html">démo en ligne</a>).</span></span></p> +</div> + +<h2 id="Résumé">Résumé</h2> + +<p><span id="result_box" lang="fr"><span>Nous espérons que vous vous êtes amusé à écrire votre propre exemple de balles aléatoires bondissantes comme dans le monde réel, en utilisant diverses techniques orientées objet et divers objets d'un bout à l'autre du module !</span> Nous espérons vous avoir offert un aperçu<span> utile de l'utilisation des objets.</span><br> + <br> + <span>C'est tout pour les articles sur les objets </span></span>—<span lang="fr"><span> il ne vous reste plus qu'à tester vos compétences dans l'évaluation sur les objets.</span></span></p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Canvas_API/Tutorial">Didacticiel sur canvas</a> — <span id="result_box" lang="fr"><span>un guide pour débutants sur l'utilisation de canvas 2D.</span></span></li> + <li><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></li> + <li><span id="result_box" lang="fr"><span><a href="/en-US/docs/Games/Techniques/2D_collision_detection">Détection de collision 2D</a> </span></span></li> + <li><span id="result_box" lang="fr"><span><a href="/en-US/docs/Games/Techniques/3D_collision_detection">Détection de collision 3D</a> </span></span></li> + <li><a href="/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript">Jeu d'évasion 2D utilisant du JavaScript pu</a> —<span id="result_box" lang="fr"><span>un excellent tutoriel pour débutant montrant comment construire un jeu en 2D.</span></span></li> + <li><a href="/en-US/docs/Games/Tutorials/2D_breakout_game_Phaser">Jeu d'évasion 2D utilisant phaser</a> — <span id="result_box" lang="fr"><span>explique les bases de la construction d'un jeu 2D en utilisant une bibliothèque de jeux JavaScript.</span></span></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</p> + + + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Les bases de l'objet</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orienté objet pour les débutants</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Prototypes d'objets</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Héritage en JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Travailler avec des données JSON</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Pratique de construction d'objets</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Ajout de fonctionnalités à notre démo de balles bondissantes</a></li> +</ul> diff --git a/files/fr/learn/javascript/objects/prototypes_objet/index.html b/files/fr/learn/javascript/objects/prototypes_objet/index.html new file mode 100644 index 0000000000..efb3681f18 --- /dev/null +++ b/files/fr/learn/javascript/objects/prototypes_objet/index.html @@ -0,0 +1,244 @@ +--- +title: Prototypes Objet +slug: Learn/JavaScript/Objects/Prototypes_Objet +tags: + - Constructeur + - JavaScript + - Prototype +translation_of: Learn/JavaScript/Objects/Object_prototypes +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Les prototypes sont un mécanisme au sein de JavaScript qui permettent aux objets JavaScript d'hériter des propriétés d'autres objets. Les prototypes implémentent un héritage différent de celui rencontré dans les langages de programmation objets habituels. Dans cet article, nous allons aborder ces différences, nous allons aussi voir comment la chaîne de prototypage fonctionne. Nous verrons aussi comment les propriétés prototypes peuvent être utilisées afin d'ajouter des méthodes à des constructeurs existants.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td>Une connaissance générale de l'informatique, des notions d'HTML et CSS, une connaissance des bases en JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction</a>) ainsi que des notions de JavaScript orienté objet (JSOO) (voir <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>).</td> + </tr> + <tr> + <th scope="row">Objectifs :</th> + <td>Comprendre le concept de prototype en JavaScript, comprendre comment fonctionne une chaîne de prototypage et comment ajouter de nouvelles méthodes aux propriétés d'un prototype.</td> + </tr> + </tbody> +</table> + +<h2 id="Un_langage_basé_sur_des_prototypes">Un langage basé sur des prototypes ?</h2> + +<p>JavaScript est souvent décrit comme un langage basé sur les prototypes, chaque objet pouvant avoir un <strong>prototype objet</strong> d'où il hérite des méthodes et des attributs. Un prototype peut lui aussi avoir son prototype objet duquel il héritera des méthodes et des attributs et ainsi de suite. On parle alors de chaîne de prototypage (ou <em>prototype chain<strong> </strong></em>en anglais). Cela permet d'expliquer pourquoi différents objets possèdent des attributs et des méthodes définis à partir d'autres objets.</p> + +<p>En réalité, les méthodes et attributs sont définis dans l'attribut <code>prototype</code> , la fonction constructrice de l'objet et non pas dans les instances des objets elles-mêmes.</p> + +<p>En programmation orientée objet classique, les classes sont définies, puis lorsque des instances sont créées, l'ensemble des attributs et des méthodes sont copiés dans l'instance. En JavaScript en revanche, tout n'est pas copié : on établit un lien entre l'objet instancié et son constructeur (c'est un lien dans la chaîne de prototypage). On détermine alors les méthodes et les attributs en remontant la chaîne.</p> + +<div class="note"> +<p><strong>Note:</strong> Il faut bien comprendre qu'il y a une différence entre la notion de prototype d'un objet (qu'on obtient via <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf">Object.getPrototypeOf(obj)</a></code>, ou via la propriété dépréciée <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code> ) et l' attribut <code>prototype</code>d'une fonction constructrice. La première concerne chaque instance, le dernier existe uniquement sur une fonction constructrice. Cela dit, <code>Object.getPrototypeOf(new Foobar())</code> renvoie au même object que<code>Foobar.prototype</code>.</p> +</div> + +<p>Prenons un exemple afin de rendre cela un peu plus clair.</p> + +<h2 id="Comprendre_les_prototypes_objet">Comprendre les prototypes objet</h2> + +<p>Reprenons notre exemple dans lequel nous avions écrit notre constructeur <code>Personne()</code>. Chargez cet exemple dans votre navigateur, si vous ne l'avez plus, vous pouvez utiliser notre exemple<a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html"> oojs-class-further-exercises.html</a> example (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">code source</a>).</p> + +<p>Dans cet exemple, nous avons défini un constructeur comme suit :</p> + +<pre class="brush: js">function Personne(prenom, nom, age, genre, interets) { + + // property and method definitions + +};</pre> + +<p>Nous avons ensuite instancié des objets comme ceci :</p> + +<pre class="brush: js">var personne1 = new Personne('Bob', 'Smith', 32, 'homme', ['musique', 'ski']);</pre> + +<p>Si vous entrez « <code>personne1</code> » dans votre console JavaScript, vous devriez voir que le navigateur essaie de faire de l'auto-complétion avec les attributs de cet objet.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14907/autocomplete_Personne.png" style="height: 304px; width: 288px;"><img alt="" src="https://mdn.mozillademos.org/files/14919/autocomplete_Personne.png" style="height: 288px; width: 303px;"></p> + +<p>Dans cette liste vous verrez les membres définis au niveau du constructeur de <code>personne1</code> qui n'est autre <code>Personne()</code>. On y trouve les valeurs suivantes : <code>nom</code>, <code>age</code>, <code>genre</code>, <code>interets</code>, <code>bio</code>, et <code>salutation</code>. On peut voir aussi d'autres membres tels que <code>watch</code>, <code>valueOf</code> … Ces membres particuliers sont définis au niveau du prototype objet du constructeur <code>Personne()</code>, qui est <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code>. On voit ici une mise en œuvre de la chaine de prototypage.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14921/prototype_chaine.PNG" style="height: 137px; width: 703px;"></p> + +<p>Que peut-il bien se passer lorsque l'on tente d'appeler une méthode définie pour <code>Object</code> en l'appliquant à <code>Personne</code>1 ? Par exemple :</p> + +<pre class="brush: js">personne1.valueOf()</pre> + +<p>Cette méthode renvoie simplement la valeur de l'objet pour lequel elle est appelée. Vous pouvez essayer dans votre console ! Lorsque l'on effectue cet appel, il se produit les choses suivantes :</p> + +<ul> + <li>Le navigateur tente de déterminer si l'objet <code>personne1</code> implémente une méthode <code>valueOf().</code></li> + <li>Aucune n'est présente, le navigateur vérifie donc si le prototype objet de <code>personne1</code> (<code>Personne</code>) contient cette méthode.</li> + <li>Pas de <code>valueOf()</code> non plus, donc le navigateur regarde si le prototype objet du constructeur <code>Personne()</code> (<code>Object</code>) possède cette méthode. Il y en a une, donc il l'appelle et tout va bien !</li> +</ul> + +<div class="note"> +<p><strong>Note </strong>: Encore une fois, il est important d'insister sur le fait que les méthodes et attributs ne sont <strong>pas</strong> copiés d'un objet à un autre, mais qu'on y accède à chaque fois en remontant la chaine de prototypage.</p> +</div> + +<div class="note"> +<p><strong>Note</strong> : Il n'existe pas de façon officielle d'accéder directement au prototype d'un objet donné. Les « liens » entre les éléments de la chaine sont définis au sein d'une propriété interne appelée <code>[[prototype]]</code> définie dans la spécification de JavaScript. (voir <a href="fr/docs/Web/JavaScript/Language_Resources">ECMAScript</a>). Néanmoins, la plupart des navigateurs modernes implémentent l'attribut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code> (deux tirets soulignés ou <em>underscore</em> de chaque côté) qui contient le prototype objet d'un objet. Vous pouvez tenter <code>personne1.__proto__</code> et <code>personne1.__proto__.__proto__</code> pour voir à quoi ressemble une chaine de prototypage dans la console !</p> +</div> + +<h2 id="Lattribut_prototype_là_où_lon_définit_les_éléments_héritables">L'attribut prototype : là où l'on définit les éléments héritables</h2> + +<p>Mais alors, où définissons-nous les attributs et méthodes qui seront hérités au long de la chaîne de prototypage ? En effet, s'il on regarde à la page de documentation <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code> on peut voir un large éventail d'attributs et de méthodes qui sont définis, une liste bien plus longue que celle disponible pour notre objet <code>Personne1</code>. Pourquoi <code>Personne1</code> hérite de certains de ces éléments mais pas de tous ?</p> + +<p>Cela vient du fait que les éléments hérités sont ceux définis au niveau de l'attribut <code>prototype</code> d'<code>Object</code> (on peut voir cet attribut comme un sous espace de noms). Ainsi, les éléments listés sont ceux sous <code>Object.prototype.</code> et pas ceux situés juste sous <code>Object.</code> La valeur de l'attribut <code>prototype</code> est un objet qui rassemble les attributs et méthodes que l'on souhaite appliquer aux objets tout au long de la chaine de prototypage.</p> + +<p>Ainsi <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/watch">Object.prototype.watch()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf">Object.prototype.valueOf()</a></code> … sont disponibles pour n'importe quel objet qui hérite de <code>Object.prototype</code> ce qui inclus les nouvelles instances créées à partir du constructeur <code>Personne()</code>.</p> + +<p><code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/is">Object.is()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>, ainsi que d'autres membres non définis dans <code>prototype</code> ne sont pas hérités par les instances d'objet ou les objets qui héritent de <code>Object.prototype</code>. Ces méthodes et attributs sont disponibles uniquement pour le constructeur <code>Object()</code>.</p> + +<div class="note"> +<p><strong>Note</strong> : Ça paraît bizarre, d'avoir une méthode définie au sein d'un constructeur qui est lui même une fonction non ? Et bien, une fonction est aussi un type d'objet — vous pouvez jeter un œil à la documentation du constructeur <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function">Function()</a></code> si vous ne nous croyez pas.</p> +</div> + +<ol> + <li>Vous pouvez vérifier les attributs du prototype en reprenant l'exemple précédent et en entrant le code suivant dans la console JavaScript : + <pre class="brush: js">Personne.prototype</pre> + </li> + <li>Il n'y a pas grand chose renvoyé par le navigateur. En même temps, nous n'avons rien défini dans l'attribut prototype de notre constructeur, et par défaut l'attribut prototype d'un constructeur est toujours vide. Voyons ce que renvoie le code suivant : + <pre class="brush: js">Object.prototype</pre> + </li> +</ol> + +<p>On observe que plusieurs méthodes sont définies au niveau de l'attribut <code>prototype</code> d'<code>Object</code>, qui seront alors disponibles pour les objets qui héritent d'<code>Object</code>, comme nous l'avons vu plus haut.</p> + +<p>Vous verrez qu'il existe plein d'exemples de chaine de prototypage dans JavaScript. Vous pouvez essayer de trouver les méthodes et les attributs définis dans les attributs <code>prototype</code> des objets globeaux comme <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date">Date</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number">Number</a></code>, et <code> <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code>. Chacun de ces objets possède des éléments au sein de leur attribut prototype. Dès lors que l'on crée une chaine de caractères, comme celle-ci :</p> + +<pre class="brush: js">var maChaine = 'Ceci est ma chaine de caracteres.';</pre> + +<p><code>maChaine </code>possède aussitôt plusieurs méthodes utiles pour manipuler les chaines de caractères telles que <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/split">split()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf">indexOf()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a></code>…</p> + +<div class="warning"> +<p><strong>Important </strong>: L'attribut <code>prototype</code> est un des éléments JavaScript qui peut le plus prêter à confusion. On pourrait penser qu'il s'agit du prototype objet de l'objet courant mais ça ne l'est pas (on peut y accéder via <code>__proto__</code>). L'attribut <code>prototype </code>est un attribut qui contient un objet où l'on définit les éléments dont on va pouvoir hériter.</p> +</div> + +<h2 id="Revenons_sur_create">Revenons sur create()</h2> + +<p>Nous avons vu précedemment que la méthode <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></code> pouvait être utilisée pour instancier des objets.</p> + +<ol> + <li>Par exemple, vous pouvez essayer le code suivant dans la console JavaScript : + <pre class="brush: js">var personne2 = Object.create(personne1);</pre> + </li> + <li>En réalité <code>create()</code> se contente de créer un nouvel objet à partir d'un prototype spécifique. Dans cet exemple, <code>personne2</code> est créé à partir de <code>personne1</code> qui agit en tant que prototype. Vous pouvez le vérifier via : + <pre class="brush: js">person2.__proto__</pre> + </li> +</ol> + +<p>Cela renverra l'objet <code>personne1</code>.</p> + +<h2 id="Lattribut_constructor">L'attribut <em>constructor</em></h2> + +<p>Chaque fonction possède un attribut prototype dont la valeur est un objet contenant un attribut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code>. L'attribut <code>constructor</code> renvoie vers la méthode constructrice utilisée. Nous allons le voir dans la section suivante, les attributs définis dans l'attribut <code>Personne.prototype</code> deviennent disponibles pour toutes les instances créées à partir du constructeur <code>Personne()</code>. De cette manière, l'attribut <code>constructor</code> est aussi disponible au sein de <code>personne1</code> et <code>personne2</code>.</p> + +<ol> + <li>Par exemple, vous pouvez tester le code suivant : + <pre class="brush: js">personne1.constructor +personne2.constructor</pre> + + <p>Chaque commande devrait renvoyer le constructeur <code>Personne()</code> étant donné qu'il a permis d'instancier ces objets.</p> + + <p>Une astuce qui peut s'avérer utile est d'ajouter des parenthèses à la fin de l'attribut <code>constructor</code> pour le transformer en méthode. Après tout, le constructeur est une fonction que l'on peut appeler si besoin. Il faut juste utiliser le mot-clé <code>new</code> pour signifier que l'on souhaite construire un objet.</p> + </li> + <li>Par exemple : + <pre class="brush: js">var personne3 = new personne1.constructor('Karen', 'Stephenson', 26, 'femme', ['jouer de la batterie', 'escalade']);</pre> + </li> + <li>Vous pouvez désormais essayer d'accéder aux propriétés de personne3 : + <pre class="brush: js">personne3.prenom +personne3.age +personne3.bio()</pre> + </li> +</ol> + +<p>Ça fonctionne bien. A priori, ce n'est pas la manière la plus simple de créer un objet et vous n'aurez pas à l'utiliser souvent. En revanche, ça peut vous débloquer quand vous devez créer une nouvelle instance et que vous ne disposez pas facilement du constructeur d'origine.</p> + +<p>L'attribut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code> possède d'autres intérêts. Par exemple, si vous disposez du nom d'une instance objet vous pouvez utiliser le code suivant pour renvoyer le nom de son constructeur :</p> + +<pre class="brush: js">instanceName.constructor.name</pre> + +<p>Vous pouvez essayer :</p> + +<pre class="brush: js">personne1.constructor.name</pre> + +<h2 id="Modifions_les_prototypes">Modifions les prototypes</h2> + +<p>Voyons au travers d'un exemple comment modifier l'attribut <code>prototype</code> d'un constructeur (les méthodes ajoutées au prototype seront alors disponibles pour toutes les instances créées à partir du constructeur).</p> + +<ol> + <li>Revenons à notre exemple <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">oojs-class-further-exercises.html</a> et faisons une copie local du <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">code source</a>. En dessous du JavaScript existant, vous pouvez ajouter le code suivant, ce qui aura pour effet d'ajouter une nouvelle méthode à l'attribut <code>prototype</code> du constructeur : + + <pre class="brush: js">Personne.prototype.aurevoir = function() { + alert(this.nom.prenom + ' est sorti. Au revoir !'); +}</pre> + </li> + <li>Enregistrez vos modifications et chargez la page dans votre navigateur. Vous pouvez ensuite entrer le code suivant dans la console : + <pre class="brush: js">personne1.aurevoir();</pre> + </li> +</ol> + +<p>Vous devriez voir une fenêtre s'afficher avec un message contenant le nom de la personne. Cette fonctionalité est utile, mais là où ça devient plus intéressant c'est que la chaine de prototypage a été mis à jour dynamiquement, rendant automatiquement cette méthode disponible à l'ensemble des instances existantes.</p> + +<p>Revoyons en détail ce qui s'est passé : tout d'abord, nous avons défini le constructeur. Ensuite, nous avons instancié un objet à partir du constructeur. Enfin, nous avons ajouté une nouvelle méthode au prototype du construceur :</p> + +<pre class="brush: js">function Personne(prenom, nom, age, genre, interets) { + + // définition des attrbuts et des méthodes + +}; + +var personne1 = new Personne('Tammi', 'Smith', 32, 'neutre', ['musique', 'ski', 'kickboxing']); + +Personne.prototype.aurevoir= function() { + alert(this.nom.prenom + ' est sorti. Au revoir !'); +}</pre> + +<p>Même si nous l'avons déclaré après, la méthode <code>aurevoir()</code> est disponible pour l'instance <code>personne1</code>. Son existence a mis à jour dynamiquement les méthodes de l'instance. Cela démontre ce que nous expliquions plus haut au sujet de la chaine de prototypage : le navigateur la parcourt de manière ascendante. Ainsi, il est possible de trouver directement les méthodes qui n'ont pas été définies au niveau de l'instance, plutôt que de les recopier au sein de l'instance. Cela nous permet de bénéficier d'un système extensible de manière simple et élégante.</p> + +<div class="note"> +<p><strong>Note </strong>: Si vous avez du mal à faire fonctionner cet exemple, vous pouvez jeter un œil au notre (<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-prototype.html">oojs-class-prototype.html</a>, voir la <a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-prototype.html">démo</a>)</p> +</div> + +<p>Vous verrez peu d'attributs définis au sein de l'attribut <code>prototype</code>, pour la simple et bonne raison que c'est assez peu pratique. Vous pourriez avoir :</p> + +<pre class="brush: js">Personne.prototype.nomComplet = 'Bob Smith';</pre> + +<p>Mais ce n'est pas très pratique, étant donné qu'une personne ne sera peut-être pas appelée de cette manière. Il est plus cohérent de construire le nom entier en combinant le nom et le prénom :</p> + +<pre class="brush: js">Personne.prototype.nomComplet = this.nom.prenom + ' ' + this.nom.nom;</pre> + +<p>Ça ne fonctionnera toujours pas. En effet, <code>this</code> aura une portée globale et ne sera pas dans le contexte de la fonction. En appelant cet attribut, nous aurions alors <code>undefined undefined</code>. Dans les exemples précédents sur le prototype, nous arrivions à obtenir quelque chose de fonctionnel puisque nous étions au sein d'une méthode, qui sera utilisée par l'instance. Il est donc possible de définir des attributs invariables au niveau du prototype mais de manière générale, il est préférable de les définir au sein du constructeur.</p> + +<p>En fait, on retrouve généralement la chose suivante : les attributs sont définis dans le constructeur, tandis que les méthodes sont définies au niveau du prototype. Cela rend le code plus simple à lire puisque les attributs sont groupés et les méthodes structurées en blocs distincts. Par exempe :</p> + +<pre class="brush: js">// Constructeur avec définition des attributs + +function Test(a, b, c, d) { + // définition des attributs +}; + +// Définition de la première méthode + +Test.prototype.x = function() { ... } + +// Définition de la seconde méthode + +Test.prototype.y = function() { ... } + +// etc...</pre> + +<p>Ce type d'implémentation peut être observée dans l'appli <a href="https://github.com/zalun/school-plan-app/blob/master/stage9/js/index.js">plan d'école</a> de Piotr Zalewa par exemple.</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Cet article a traité des prototypes objet en JavaScript, en incluant la chaine de prototypage qui permet aux objets d'hériter des propriétés d'un autre objet. Nous avons aussi vu l'attribut prototype et comment nous pouvons l'utiliser pour ajouter des méthodes au constructeur.</p> + +<p>Dans le prochain article, nous verrons comment appliquer l'héritage entre deux de nos propres objets.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</p> |