aboutsummaryrefslogtreecommitdiff
path: root/files
diff options
context:
space:
mode:
Diffstat (limited to 'files')
-rw-r--r--files/fr/web/javascript/guide/details_of_the_object_model/index.html983
1 files changed, 460 insertions, 523 deletions
diff --git a/files/fr/web/javascript/guide/details_of_the_object_model/index.html b/files/fr/web/javascript/guide/details_of_the_object_model/index.html
index ad95d59b18..24c1a3c533 100644
--- a/files/fr/web/javascript/guide/details_of_the_object_model/index.html
+++ b/files/fr/web/javascript/guide/details_of_the_object_model/index.html
@@ -9,612 +9,552 @@ tags:
translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model
original_slug: Web/JavaScript/Guide/Le_modèle_objet_JavaScript_en_détails
---
-<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Utiliser_les_objets", "Web/JavaScript/Guide/Utiliser_les_promesses")}}</p>
+<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Using_promises")}}</div>
-<p class="summary">JavaScript est un langage objet basé sur des prototypes plus que sur des classes. Cette différence peut rendre difficile la compréhension des hiérarchies entre objets, leurs créations, l’héritage de propriétés et de leurs valeurs... L’objectif de ce chapitre est de clarifier ces différents éléments en expliquant le modèle prototypal et ses différences avec un système de classes.</p>
+<p class="summary">JavaScript est un langage orienté objet basé sur des prototypes, plutôt que sur des classes. En raison de cette base différente, il peut être moins évident de comprendre comment JavaScript vous permet de créer des hiérarchies d'objets et d'avoir un héritage des propriétés et de leurs valeurs. Ce chapitre tente de clarifier la situation.</p>
-<p>Avant de lire ce chapitre, il est conseillé d’avoir quelques bases en JavaScript, notamment en ayant déjà écrit quelques fonctions et manipulé des objets.</p>
+<p>Ce chapitre part du principe que vous avez déjà une certaine connaissance de JavaScript et que vous avez utilisé des fonctions JavaScript pour créer des objets simples.</p>
-<h2 id="Langages_de_prototypes_Langages_de_classes">Langages de prototypes / Langages de classes</h2>
+<h2 id="class-based_vs._prototype-based_languages">Langages basés sur des classes ou des prototypes</h2>
-<p>Les langages orientés objet basés sur des classes, comme Java ou C++, se fondent sur deux entités principales distinctes : les classes et les instances.</p>
+<p>Les langages orientés objets, basés sur des classes, tels que Java et C++, sont fondés sur le concept de deux entités distinctes : les classes et les instances.</p>
<ul>
- <li>Une <em>classe</em> définit l’ensemble des propriétés (que ce soit les méthodes et les attributs en Java, ou les membres en C++) caractérisant un certain ensemble d’objets. Une classe est une représentation abstraite et non pas la représentation particulière d'un membre de cet ensemble d'objets. Par exemple, la classe <code>Employé</code> permettrait de représenter l’ensemble de tous les employés.</li>
- <li>Une <em>instance</em> correspond à l’instanciation d'une classe. C’est un de ses membres. Ainsi,<code> Victoria</code> pourrait être une instance de la classe <code>Employé</code> et représenterait un individu en particulier comme un employé. Une instance possède exactement les mêmes propriétés que sa classe (ni plus ni moins).</li>
+ <li>Une <em>classe</em> définit toutes les propriétés qui caractérisent un certain ensemble d'objets (en considérant les méthodes et les champs en Java, ou les membres en C++, comme des propriétés). Une classe est abstraite par opposition à un membre particulier d'un ensemble d'objets qu'elle décrit. Par exemple, la classe <code>Employee</code> pourrait représenter l'ensemble de tous les employés.</li>
+ <li>Une <em>instance</em>, par contre, est l'instanciation d'une classe. Par exemple, <code>Victoria</code> pourrait être une instance de la classe <code>Employee</code>, représentant un individu particulier en tant qu'employé. Une instance possède exactement les mêmes propriétés que sa classe parente (ni plus, ni moins).</li>
</ul>
-<p>Un langage basé sur des prototypes, comme JavaScript, n’utilise pas cette distinction. Il ne possède que des objets. On peut avoir des objets <em>prototypiques</em> qui sont des objets agissant comme un modèle sur lequel on pourrait obtenir des propriétés initiales pour un nouvel objet. Tout objet peut définir ses propres propriétés, que ce soit à l’écriture ou pendant l’exécution. De plus, chaque objet peut être associé comme le <em>prototype</em> d’un autre objet, auquel cas le second objet partage les propriétés du premier.</p>
+<p>Un langage basé sur des prototypes, tel que JavaScript, ne fait pas cette distinction : il a des objets. Un langage basé sur des prototypes possède la notion d'un <em>objet prototypique</em>, un objet utilisé comme modèle à partir duquel on peut obtenir les propriétés initiales d'un nouvel objet. Tout objet peut spécifier ses propres propriétés, soit lors de sa création, soit au moment de l'exécution. En outre, tout objet peut être associé en tant que <em>prototype</em> d'un autre objet, permettant au second objet de partager les propriétés du premier.</p>
-<h3 id="La_définition_dune_classe">La définition d'une classe</h3>
+<h3 id="defining_a_class">La définition d'une classe</h3>
-<p>Dans les langages de classes, on doit définir une classe dans une <em>définition de classe</em>. Dans cette définition, on peut inclure certaines méthodes spéciales, comme les <em>constructeurs</em> qui permettent de créer de nouvelles instances de cette classe. Un constructeur permet de définir certaines valeurs initiales pour des propriétés de l’instance et d’effectuer certains traitements lors de la création d’une instance. L’opérateur <code>new</code>, utilisé avec le constructeur, permet de créer de nouvelles instances.</p>
+<p>Dans les langages basés sur les classes, vous définissez une classe en utilisant une <em>définition de classe</em> distincte. Dans cette définition, vous pouvez spécifier des méthodes spéciales, appelées <em>constructeur</em> (et écrites « constructor »), pour créer des instances de la classe. Une méthode constructrice peut spécifier des valeurs initiales pour les propriétés de l'instance et effectuer d'autres traitements appropriés au moment de la création. Vous utilisez l'opérateur <code>new</code> en association avec la méthode constructrice pour créer des instances de la classe.</p>
-<p>Le fonctionnement de JavaScript est similaire. En revanche, il n’y a pas de différence entre la définition de la classe et le constructeur. La fonction utilisée pour le constructeur permet de créer un objet avec un ensemble initial de propriétés et de valeurs. Toute fonction JavaScript peut être utilisée comme constructeur. L’opérateur <code>new</code> doit être utilisé avec un constructeur pour créer un nouvel objet.</p>
+<p>JavaScript suit un modèle similaire, mais ne dispose pas d'une définition de classe distincte de celle du constructeur. Au lieu de cela, vous définissez une fonction de construction pour créer des objets avec un ensemble initial particulier de propriétés et de valeurs. Toute fonction JavaScript peut être utilisée comme constructeur. Vous utilisez l'opérateur <code>new</code> avec une fonction « constructor » pour créer un nouvel objet.</p>
-<div class="blockIndicator note">
-<p><strong>Note :</strong> Bien qu'ECMAScript 2015 introduise <a href="/fr/docs/Web/JavaScript/Reference/Classes">une déclaration de classe</a>, celle-ci n'est qu'un sucre syntaxique utilisant l'héritage à base de prototype. Cette nouvelle syntaxe n'introduit pas de nouveau paradigme d'héritage objet au sein de JavaScript.</p>
+<div class="note">
+ <p><strong>Note :</strong> ECMAScript 2015 introduit une <a href="/fr/docs/Web/JavaScript/Reference/Classes">déclaration de classe</a> :</p>
+
+ <blockquote>
+ <p>Les classes JavaScript, introduites dans ECMAScript 2015, sont principalement un enrichissement syntaxique de l'héritage basé sur les prototypes existant dans JavaScript. La syntaxe des classes n'introduit pas un nouveau modèle d'héritage orienté objet dans JavaScript.</p>
+ </blockquote>
</div>
-<h3 id="Classes-filles_et_héritage">Classes-filles et héritage</h3>
+<h3 id="subclasses_and_inheritance">Classes enfants et héritage</h3>
-<p>Dans un langage de classes, on peut créer une hiérarchie de classes à travers la définition de classe. En effet, dans cette définition, on peut préciser si la nouvelle classe est une classe-fille d'une classe existante. La classe-fille hérite alors des propriétés de la classe-parente et peut ajouter de nouvelles propriétés ou modifier les propriétés héritées. Si, par exemple, la classe <code>Employé</code> comprend les propriétés <code>nom</code> et <code>branche</code> et que <code>Manager</code> est une classe-fille de la classe <code>Employee</code> qui ajoute la propriété <code>rapports</code>. Dans cet exemple, une instance de la classe <code>Manager</code> aurait trois propriétés : <code>nom</code>, <code>branche</code>, et <code>rapports</code>.</p>
+<p>Dans un langage basé sur les classes, vous créez une hiérarchie de classes par le biais des définitions de classes. Dans une définition de classe, vous pouvez spécifier que la nouvelle classe est une <em>classe enfant</em> d'une classe déjà existante. La classe enfant hérite de toutes les propriétés de la classe parente et peut en plus ajouter de nouvelles propriétés ou modifier celles héritées. Par exemple, supposons que la classe <code>Employee</code> ne comprend que les propriétés <code>name</code> (« nom ») et <code>dept</code> (« département »), et que <code>Manager</code> est une classe enfant de <code>Employee</code> qui ajoute la propriété <code>reports</code> (« rapports »). Dans ce cas, une instance de la classe <code>Manager</code> aurait les trois propriétés : <code>name</code>, <code>dept</code>, et <code>reports</code>.</p>
-<p>En JavaScript, l’héritage permet d’associer un objet prototypique avec n’importe quel constructeur. Ainsi, on peut créer le même exemple <code>Employé</code> — <code>Manager</code> mais on utilisera une terminologie légèrement différente. Tout d’abord, on définit le constructeur (fonction) <code>Employé</code> et on y définit les propriétés <code>nom</code> et <code>branche</code>. Ensuite, on définit le constructeur <code>Manager</code> avec la propriété <code>rapports</code>. Enfin, on assigne un nouvel objet <code>Employé</code> comme <code>prototype</code> dans le constructeur <code>Manager</code>. Ainsi, quand on créera un nouvel objet <code>Manager</code>, il héritera des propriétés <code>nom</code> et <code>branche</code> de l’objet <code>Employé</code>.</p>
+<p>JavaScript met en œuvre l'héritage en vous permettant d'associer un objet prototypique à n'importe quelle fonction de construction. Ainsi, vous pouvez créer exactement l'exemple <code>Employee</code> — <code>Manager</code>, mais vous utilisez une terminologie légèrement différente. D'abord, vous définissez la fonction du constructeur <code>Employee</code>, en spécifiant les propriétés <code>name</code> et <code>dept</code>. Ensuite, vous définissez la fonction du constructeur <code>Manager</code>, en appelant le constructeur <code>Employee</code> et en spécifiant la propriété <code>reports</code>. Enfin, vous attribuez un nouvel objet dérivé de <code>Employee.prototype</code> comme <code>prototype</code> pour la fonction du constructeur <code>Manager</code>. Ensuite, lorsque vous créez un nouveau <code>Manager</code>, il hérite des propriétés <code>name</code> et <code>dept</code> de l'objet <code>Employee</code>.</p>
-<h3 id="Ajouter_ou_retirer_des_propriétés">Ajouter ou retirer des propriétés</h3>
+<h3 id="adding_and_removing_properties">Ajouter ou retirer des propriétés</h3>
-<p>Dans un langage de classe, les classes sont créées durant la compilation et les instanciations de la classe ont lieu durant la compilation ou durant l’exécution. Il n’est pas possible de modifier les propriétés (leur quantité, leurs types) une fois que la classe a été définie. JavaScript, en revanche, permet d’ajouter ou de retirer des propriétés à n’importe quel objet pendant l’exécution. Si une propriété est ajoutée à un objet utilisé comme prototype, tous les objets qui l’utilisent comme prototype bénéficieront de cette propriété.</p>
+<p>Dans les langages basés sur les classes, vous créez généralement une classe au moment de la compilation, puis vous instanciez, des instances de la classe, soit au moment de la compilation, soit au moment de l'exécution. Vous ne pouvez pas modifier le nombre ou le type de propriétés d'une classe après avoir défini cette dernière. En JavaScript, cependant, au moment de l'exécution, vous pouvez ajouter ou supprimer des propriétés de tout objet. Si vous ajoutez une propriété à un objet qui est utilisé comme prototype pour un ensemble d'objets, les objets dont il est le prototype obtiennent également la nouvelle propriété.</p>
-<h3 id="Résumé_des_différences">Résumé des différences</h3>
+<h3 id="summary_of_differences">Résumé des différences</h3>
-<p>Le tableau suivant fournit un rapide récapitulatif de ces différences. Le reste du chapitre décrira l’utilisation de constructeur et de prototypes en JavaScript ainsi que la méthode correspondante qui pourrait être utilisée en Java.</p>
+<p>Le tableau suivant donne un bref résumé de certaines de ces différences. Le reste de ce chapitre décrit les détails de l'utilisation des constructeurs et prototypes JavaScript pour créer une hiérarchie d'objets et les compare à la façon dont vous le feriez en Java.</p>
<table class="standard-table">
- <thead>
- <tr>
- <th scope="col">Catégorie</th>
- <th scope="col">Langage de classe (Java)</th>
- <th scope="col">Langage de prototype (JavaScript)</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>Classe ou instance</td>
- <td>Les classes et les instances sont deux entités distinctes.</td>
- <td>Tous les objets sont des instances.</td>
- </tr>
- <tr>
- <td>Définition</td>
- <td>Une classe est définie avec une définition de classe. On instancie une classe avec des méthodes appelées constructeurs</td>
- <td>On définit et on crée un ensemble d’objets avec des fonctions qui sont des constructeurs.</td>
- </tr>
- <tr>
- <td>Création d'un nouvel objet</td>
- <td>On crée un seul objet grâce à l’opérateur <code>new</code>.</td>
- <td>Même chose que pour les langages de classe.</td>
- </tr>
- <tr>
- <td>Construction de la hiérarchie des objets</td>
- <td>On construit une hiérarchie d’objets en utilisant les définitions des classes pour définir des classes-filles à partir de classes existantes.</td>
- <td>On construit une hiérarchie d’objets en assignant un prototype à un objet dans le constructeur de cet objet.</td>
- </tr>
- <tr>
- <td>Modèle d'héritage</td>
- <td>Les objets héritent des propriétés appartenant à la chaîne des classes de la hiérarchie.</td>
- <td>Les objets héritent des propriétés appartenant à la chaîne des prototypes de la hiérarchie.</td>
- </tr>
- <tr>
- <td>Ajout de propriétés</td>
- <td>La définition de la classe définit exactement toutes les propriétés de toutes les instances d’une classe. Il est impossible d’ajouter des propriétés dynamiquement pendant l’exécution.</td>
- <td>Le constructeur ou le prototype définit un ensemble de propriétés initiales. Il est possible d’ajouter ou de retirer des propriétés dynamiquement, pour certains objets en particuliers ou bien pour l’ensemble des objets.</td>
- </tr>
- </tbody>
+ <caption>Comparaison des systèmes d'objets basés sur des classes (Java) et des prototypes (JavaScript)</caption>
+ <thead>
+ <tr>
+ <th scope="row">Catégorie</th>
+ <th scope="col">Basé sur les classes (Java)</th>
+ <th scope="col">Basé sur des prototypes (JavaScript)</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th scope="row">Classe et instance</th>
+ <td>La classe et l'instance sont des entités distinctes.</td>
+ <td>Tous les objets peuvent hériter d'un autre objet.</td>
+ </tr>
+ <tr>
+ <th scope="row">Définition</th>
+ <td>Définir une classe avec une définition de classe ; instancier une classe avec des méthodes de construction.</td>
+ <td>Définir et créer un ensemble d'objets avec des fonctions de construction.</td>
+ </tr>
+ <tr>
+ <th scope="row">Création d'un nouvel objet</th>
+ <td>Créer un objet unique avec l'opérateur <code>new</code>.</td>
+ <td>Pareil.</td>
+ </tr>
+ <tr>
+ <th scope="row">Construction de la hiérarchie des objets</th>
+ <td>Construire une hiérarchie d'objets en utilisant des définitions de classes pour définir des classes enfants à partir de classes existantes.</td>
+ <td>Construire une hiérarchie d'objets en assignant un objet comme prototype associé à une fonction de construction.</td>
+ </tr>
+ <tr>
+ <th scope="row">Modèle d'héritage</th>
+ <td>Hériter des propriétés en suivant la chaîne de classes.</td>
+ <td>Hériter des propriétés en suivant la chaîne des prototypes.</td>
+ </tr>
+ <tr>
+ <th scope="row">Extension des propriétés</th>
+ <td>La définition de la classe spécifie <em>toutes</em> les propriétés de toutes les instances d'une classe. Impossible d'ajouter des propriétés dynamiquement au moment de l'exécution.</td>
+ <td>La fonction ou le prototype du constructeur spécifie un <em>ensemble initial</em> de propriétés. On peut ajouter ou supprimer dynamiquement des propriétés à des objets individuels ou à l'ensemble des objets.</td>
+ </tr>
+ </tbody>
</table>
-<h2 id="L’exemple_de_l’employé">L’exemple de l’employé</h2>
-
-<p>La suite de ce chapitre expliquera la hiérarchie objet suivante, modélisant un système avec différents employés :</p>
+<h2 id="the_employee_example">L'exemple de l'employé</h2>
-<p><img alt="" src="https://mdn.mozillademos.org/files/3060/figure8.1.png"></p>
+<p>Le reste de ce chapitre utilise la hiérarchie des employés présentée dans la figure suivante.</p>
-<p><small><strong>Une hiérarchie objet basique</strong></small></p>
+<p><img alt="" src="figure8.1.png"></p>
-<p>Cet exemple utilisera les objets suivants :</p>
+<p>Cela montre une hiérarchie d'objets avec les objets suivants :</p>
<ul>
- <li><code>Employé</code> qui possède la propriété <code>nom</code> (dont la valeur par défaut est la chaîne de caractères vide) et <code>branche</code> (dont la valeur par défaut est "commun").</li>
- <li><code>Manager</code> qui est basé sur <code>Employé</code>. La propriété <code>rapports</code> est ajoutée (la valeur par défaut est un tableau vide, ce sera un tableau rempli d’objets<code> Employés</code>).</li>
- <li><code>Travailleur</code> est également basé sur <code>Employé</code>. La propriété <code>project</code> est ajoutée (la valeur par défaut est un tableau vide, ce sera un tableau rempli de chaînes de caractères).</li>
- <li><code>Vendeur</code> est basé sur <code>Travailleur. </code>La propriété <code>quota</code> est ajoutée (la valeur par défaut est 100). La propriété <code>branche</code> est surchargée et vaut "ventes", indiquant que tous les vendeurs font partie du même département.</li>
- <li><code>Ingénieur</code> est basé sur <code>Travailleur</code>. La propriété <code>moteur</code> est ajoutée (la valeur par défaut est la chaîne vide) et la propriété <code>branche</code> est surchargée avec la valeur "ingénierie".</li>
+ <li><code>Employee</code> possède les propriétés <code>name</code> (« le nom » dont la valeur par défaut est la chaîne de caractères vide) et <code>dept</code> (« le département » dont la valeur par défaut est « général »).</li>
+ <li><code>Manager</code> est basé sur <code>Employee</code>. Il ajoute la propriété <code>reports</code> (« les rapports » dont la valeur par défaut est un tableau vide, destiné à avoir pour valeur un tableau d'objets <code>Employee</code>).</li>
+ <li><code>WorkerBee</code> est également basé sur <code>Employee</code>. Il ajoute la propriété <code>projects</code> (« les projets » dont la valeur par défaut est un tableau vide, destiné à avoir pour valeur un tableau de chaînes de caractères).</li>
+ <li><code>SalesPerson</code> est basé sur <code>WorkerBee</code>. Il ajoute la propriété <code>quota</code> (dont la valeur par défaut est 100). Il surcharge la propriété <code>dept</code> avec la valeur « ventes », indiquant que tous les vendeurs sont dans le même département.</li>
+ <li><code>Engineer</code> est basé sur <code>WorkerBee</code>. Il ajoute la propriété <code>machine</code> (dont la valeur par défaut est une chaîne de caractères vide) et surcharge également la propriété <code>dept</code> avec la valeur «&nbsp;ingénierie&nbsp;».</li>
</ul>
-<h2 id="La_création_de_la_hiérarchie">La création de la hiérarchie</h2>
+<h2 id="creating_the_hierarchy">La création de la hiérarchie</h2>
-<p>Plusieurs fonctions utilisées comme constructeurs peuvent permettre de définir la hiérarchie souhaitée. La façon que vous utiliserez dépendra des fonctionnalités que vous souhaitez avoir dans votre application.</p>
+<p>Il existe plusieurs façons de définir des fonctions constructrices appropriées pour mettre en œuvre la hiérarchie des employés. La façon dont vous choisissez de les définir dépend en grande partie de ce que vous voulez être en mesure de faire dans votre application.</p>
-<p>On utilise ici des définitions très simples (et peu adaptables) permettant de montrer le fonctionnement de l’héritage. Grâce à ces définitions fournies, on ne peut pas définir des valeurs spécifiques pour les propriétés lors de la création de l’objet. Les objets créés reçoivent les valeurs par défaut, les propriétés pourront être changées par la suite.</p>
+<p>Cette section montre comment utiliser des définitions très simples (et comparativement peu flexibles) pour démontrer comment faire fonctionner l'héritage. Dans ces définitions, vous ne pouvez spécifier aucune valeur de propriété lorsque vous créez un objet. L'objet nouvellement créé reçoit les valeurs par défaut, que vous pouvez modifier ultérieurement.</p>
-<p>Pour une application réelle, on définirait des constructeurs permettant de fixer les valeurs des propriétés lors de la création (voir <a href="#Des_constructeurs_plus_flexibles">Des constructeurs plus flexibles</a>). Ici, ces définitions nous permettent d’observer l’héritage.</p>
+<p>Dans une application réelle, vous définiriez probablement des constructeurs qui vous permettent de fournir des valeurs de propriété au moment de la création de l'objet (voir <a href="#more_flexible_constructors">Des constructeurs plus flexibles</a> pour plus d'informations). Pour l'instant, ces définitions simples démontrent comment l'héritage se produit.</p>
-<div class="note">
-<p>Attention, quand on assigne une fonction directement à NomFonction.prototype, cela retire la propriété « constructeur » du prototype original. Ainsi, (new Travailleur).constructor renverra un <code>Employé</code> (et non pas <code>Travailleur</code>). Il faut faire attention à la façon de conserver le constructeur original du prototype. On peut, par exemple, l'assigner à NomFonction.prototype.__proto__. Dans notre exemple, on aurait ainsi, Travailleur.prototype.__proto__ = new Employé; de cette façon : (new Travailleur).constructor renvoie bien « Travailleur ».</p>
-</div>
+<p>Les définitions suivantes en Java et en JavaScript de <code>Employee</code> sont similaires. La seule différence est que vous devez spécifier le type de chaque propriété en Java mais pas en JavaScript (ceci est dû au fait que Java est un <a href="https://en.wikipedia.org/wiki/Strong_and_weak_typing">langage fortement typé</a> <small>(en anglais)</small> alors que JavaScript est un langage faiblement typé).</p>
-<p>Les définitions d’<code>Employé</code> suivantes, en Java et JavaScript sont assez semblables. Les seules différences proviennent du typage nécessaire : avec Java, il est nécessaire de préciser le type des propriétés alors que ce n’est pas le cas en JavaScript. En Java, il est également nécessaire de créer une méthode constructeur à part dans la classe.</p>
-
-<table>
- <thead>
- <tr>
- <th scope="col">JavaScript</th>
- <th scope="col">Java</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <pre class="brush: js">
-function Employé () {
- this.nom = "";
- this.branche = "commun";
-}
-</pre>
- </td>
- <td>
- <pre class="brush: java">
-public class Employé {
- public String nom;
- public String branche;
- public Employé () {
- this.nom = "";
- this.branche = "commun";
- }
-}
-</pre>
- </td>
- </tr>
- </tbody>
-</table>
+<h4 id="javascript_using_this_may_cause_an_error_for_the_following_examples">JavaScript (l'utilisation de cette option peut provoquer une erreur pour les exemples suivants)</h4>
+
+<pre class="brush: js">class Employee {
+ constructor() {
+ this.name = '';
+ this.dept = 'général';
+ }
+}</pre>
+
+<h4 id="javascript_**_use_this_instead">JavaScript ** (utilisez plutôt ceci)</h4>
-<p>Les définitions de <code>Manager</code> et <code>Travailleur</code> permettent de voir la différence dans les façons de définir un objet plus loin dans la relation d’héritage. En JavaScript, il faut ajouter une instance prototypique comme valeur de la propriété <code>prototype</code> de la fonction constructeur (autrement dit, on définit la valeur de la propriété <code>prototype</code> de la fonction, en utilisant une instance du prototype utilisé puis en surchargeant <code>prototype.constructor</code>). On peut faire cela à n’importe quel moment après la définition du constructeur. Avec Java, on définit la classe mère au sein de la définition de la classe et il n’est pas possible de définir cette relation en dehors de la définition de la classe.</p>
-
-<table>
- <thead>
- <tr>
- <th scope="col">JavaScript</th>
- <th scope="col">Java</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <pre class="brush: js">
-function Manager () {
- this.rapports = [];
+<pre class="brush: js">function Employee() {
+ this.name = '';
+ this.dept = 'général';
+}</pre>
+
+<h4 id="java">Java</h4>
+
+<pre class="brush: java">public class Employee {
+ public String name = "";
+ public String dept = "général";
+}</pre>
+
+<p>Les définitions de <code>Manager</code> et de <code>WorkerBee</code> montrent la différence dans la façon de spécifier l'objet immédiatement supérieur dans la chaîne d'héritage. En JavaScript, vous ajoutez une instance prototypique comme valeur de la propriété <code>prototype</code> de la fonction du constructeur, puis vous surchargez le <code>prototype.constructor</code> de la fonction du constructeur. Vous pouvez le faire à tout moment après avoir défini le constructeur. En Java, vous spécifiez la superclasse dans la définition de la classe. Vous ne pouvez pas modifier la superclasse en dehors de la définition de la classe.</p>
+
+<h4 id="javascript">JavaScript</h4>
+
+<pre class="brush: js">function Manager() {
+ Employee.call(this); // On étend l'objet parent
+ this.reports = []; // On définit une propriété unique à Manager
}
-Manager.prototype = new Employé;
+Manager.prototype = Object.create(Employee.prototype); // On définit le constructeur dans prototype
+Manager.prototype.constructor = Manager; // On surchage le constructeur
-function Travailleur () {
- this.projets = [];
+function WorkerBee() {
+ Employee.call(this); // On étend l'objet parent
+ this.projects = []; // On définit une propriété unique à WorkerBee
}
-Travailleur.prototype = new Employé;
+WorkerBee.prototype = Object.create(Employee.prototype); // On définit le constructeur dans prototype
+WorkerBee.prototype.constructor = WorkerBee; // On surchage le constructeur
</pre>
- </td>
- <td>
- <pre class="brush: java">
-public class Manager extends Employé {
- public Employé[] rapports;
- public Manager () {
- this.rapports = new Employé[0];
- }
+
+<h4 id="java_2">Java</h4>
+
+<pre class="brush: java">// La classe Manager étend la classe parente Employee
+public class Manager extends Employee {
+ public Employee[] reports = new Employee[0]; // On définit une propriété unique à Manager
}
-public class Travailleur extends Employé {
- public String[] projets;
- public Travailleur () {
- this.projets = new String[0];
- }
+// La classe WorkerBee étend la classe parente Employee
+public class WorkerBee extends Employee {
+ public String[] projects = new String[0]; // On définit une propriété unique à WorkerBee
}
</pre>
- </td>
- </tr>
- </tbody>
-</table>
-<p>Les définitions d’<code>Ingénieur</code> et de <code>Vendeur</code> permettent de créer des objets qui héritent de <code>Travailleur</code> et donc, implicitement, de <code>Employé</code>. Un objet d’un de ces deux types possède les propriétés de tous les objets présents plus haut dans l’héritage. De plus, dans notre exemple, les définitions de ces types surchargent les valeurs de la propriété <code>branche</code> avec des valeurs spécifiques.</p>
-
-<table>
- <thead>
- <tr>
- <th scope="col">JavaScript</th>
- <th scope="col">Java</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <pre class="brush: js">
-function Vendeur () {
- this.branche = "ventes";
- this.quota = 100;
-}
-Vendeur.prototype = new Travailleur;
+<p>Les définitions <code>Engineer</code> et <code>SalesPerson</code> créent des objets qui descendent de <code>WorkerBee</code> et donc de <code>Employee</code>. Un objet de ces types possède les propriétés de tous les objets situés au-dessus de lui dans la hiérarchie. En outre, ces définitions remplacent la valeur héritée de la propriété <code>dept</code> par de nouvelles valeurs spécifiques à ces objets.</p>
+
+<h4 id="javascript_2">JavaScript</h4>
-function Ingénieur () {
- this.branche = "ingénierie";
- this.moteur = "";
+<pre class="brush: js">function SalesPerson() {
+ WorkerBee.call(this); // On étend l'objet WorkerBee
+ this.dept = 'ventes'; // On réécrit la valeur de « dept »
+ this.quota = 100; // On ajoute une propriété unique à SalesPerson
}
-Ingénieur.prototype = new Travailleur;
-</pre>
- </td>
- <td>
- <pre class="brush: java">
-public class Vendeur extends Travailleur {
- public double quota;
- public Vendeur () {
- this.branche = "ventes";
- this.quota = 100.0;
- }
+SalesPerson.prototype = Object.create(WorkerBee.prototype);
+SalesPerson.prototype.constructor = SalesPerson;
+
+function Engineer() {
+ WorkerBee.call(this); // On étend l'objet WorkerBee
+ this.dept = 'ingénierie'; // On réécrit la valeur de « dept »
+ this.machine = ''; // On ajoute une propriété unique à Engineer
}
+Engineer.prototype = Object.create(WorkerBee.prototype);
+Engineer.prototype.constructor = Engineer;</pre>
-public class Ingénieur extends Travailleur {
- public Ingénieur () {
- this.branche = "ingénierie";
- this.moteur = "";
- }
+<h4 id="java_3">Java</h4>
+
+<pre class="brush: java">// La classe a pour classe parente WorkerBee
+public class SalesPerson extends WorkerBee {
+ public String dept = "ventes"; // On réécrit la valeur de « dept »
+ public double quota = 100.0; // On ajoute une propriété unique à SalesPerson
}
-</pre>
- </td>
- </tr>
- </tbody>
-</table>
-<p>Grâce à ces définitions, on peut créer des instances pour ces objets qui auront les valeurs par défaut pour leurs propriétés. Le schéma suivant montre comment utiliser ces définitions en JavaScript et illustre les propriétés des objets ainsi créés.</p>
+// La classe a pour classe parente WorkerBee
+public class Engineer extends WorkerBee {
+ public String dept = "ingénierie"; // On réécrit la valeur de « dept »
+ public String machine = ""; // On ajoute une propriété unique à Engineer
+}</pre>
+
+<p>À l'aide de ces définitions, vous pouvez créer des instances de ces objets qui obtiennent les valeurs par défaut de leurs propriétés. La figure suivante illustre l'utilisation de ces définitions JavaScript pour créer de nouveaux objets et montre les valeurs des propriétés de ces nouveaux objets.</p>
<div class="note">
-<p>Le terme <em><em>instance</em></em> possède un sens particulier, au niveau technique, pour les langages de classes. Pour ces langages, une instance est le résultat de l’instanciation d’une classe en un objet (qui sera un « exemplaire » de cette classe), le concept d’instance est donc fondamentalement différent du concept de classe. En JavaScript, une « instance » ne possède pas de sens technique particulier, ceci est notamment dû au fait qu'il n’y a pas d’opposition entre ces concepts (car il n’y a pas de classe). Cependant, le terme instance peut parfois être utilisé, en JavaScript, pour désigner un objet qui aurait été créé en utilisant un constructeur. De la même façon, les mots <em><em>parent</em>, <em>enfant</em>, <em>ancêtre</em></em>, et <em><em>descendant</em></em> n’ont pas de signification formelle en JavaScript, mais ils peuvent être utilisés pour faire référence aux différents objets appartenant aux différents niveaux de la chaîne de prototypes.</p>
+ <p><strong>Note :</strong> Le terme <em>instance</em> a une signification technique spécifique dans les langages basés sur les classes. Dans ces langages, une instance est une instanciation individuelle d'une classe et est fondamentalement différente d'une classe. En JavaScript, « instance » n'a pas cette signification technique car JavaScript ne fait pas cette différence entre classes et instances. Toutefois, en parlant de JavaScript, le terme « instance » peut être utilisé de manière informelle pour désigner un objet créé à l'aide d'une fonction de construction particulière. Ainsi, dans cet exemple, vous pourriez dire de manière informelle que <code>jane</code> est une instance de <code>Engineer</code>. De même, bien que les termes <i>parent</i> (« Parent »), <i>child</i> (« Enfant »), <i>ancestor</i> (« Ancêtre ») et <i>descendant</i> (« Descendant ») n'aient pas de signification formelle en JavaScript ; vous pouvez les utiliser de manière informelle pour vous référer à des objets supérieurs ou inférieurs dans la chaîne des prototypes.</p>
</div>
-<p><img src="https://mdn.mozillademos.org/files/10412/=figure8.3.png"><strong>Créer des objets avec des définitions simples</strong></p>
+<h3 id="creating_objects_with_simple_definitions">Création d'objets avec des définitions simples</h3>
-<h2 id="Les_propriétés_d’un_objet">Les propriétés d’un objet</h2>
+<h4 id="object_hierarchy">Hiérarchie des objets</h4>
-<p>Dans cette section, nous verrons comment les objets héritent des propriétés d’autres objets de la chaîne de prototypes et de ce qui se passe quand on ajoute une propriété lors de l’exécution.</p>
+<p>La hiérarchie suivante est créée à l'aide du code situé ci-dessous.</p>
-<h3 id="L’héritage_de_propriétés">L’héritage de propriétés</h3>
+<p><img src="figure8.3.png"></p>
-<p>Imaginons qu’on souhaite créer un objet <code>marc</code> qui est un <code>Travailleur </code>:</p>
+<h4 id="individual_objects_jim_sally_mark_fred_jane_etc._instances_created_from_constructor">Objets individuels = Jim, Sally, Mark, Fred, Jane, etc.<br>« Instances » créées à partir du constructeur</h4>
-<pre class="brush: js">var marc = new Travailleur;
-</pre>
+<pre class="brush: js">let jim = new Employee;
+// Les parenthèses peuvent être omises si
+// le constructeur ne prend pas d'arguments.
+// jim.name correspond à ''
+// jim.dept correspond à 'général'.
-<p>Lorsque JavaScript rencontre l’opérateur <code>new</code>, un objet générique est créé, ce nouvel objet est passé comme valeur de <code>this</code> à la fonction constructeur de <code>Travailleur</code>. Le constructeur définit ensuite la valeur de la propriété <code>projets</code> puis il définit implicitement la valeur de la propriété interne <code>[[Prototype]]</code> avec la valeur de <code>Travailleur.prototype</code>. (Le nom de cette propriété commence et finit par deux tirets bas.) La propriété <code>__proto__</code> détermine la chaîne de prototypes utilisée pour renvoyer les valeurs des propriétés qu’on pourrait utiliser. Quand ces propriétés sont définies, JavaScript renvoie le nouvel objet, l’instruction d’assignation assigne alors la variable <code>marc</code> à cet objet.</p>
+let sally = new Manager;
+// sally.name correspond à ''
+// sally.dept correspond à 'général'
+// sally.reports correspond à []
-<p>En utilisant ce procédé, on n’introduit pas de valeurs spécifiques pour les propriétés de <code>marc</code> dont il hérite via la chaîne de prototypes. Si on utilise une valeur d'une de ces propriétés, JavaScript vérifiera tout d’abord si elle appartient à l'objet : si c’est le cas, la valeur est renvoyée. Sinon, JavaScript remonte dans la chaîne de prototypes en utilisant la propriété <code>__proto__</code>. Si un objet de cette chaîne possède une valeur pour cette propriété, la valeur est renvoyée. Si aucune propriété n’est trouvée, JavaScript indique que l’objet ne possède pas cette propriété. Ainsi pour l’objet <code>marc</code> : on aura les propriétés suivantes avec les valeurs respectives :</p>
+let mark = new WorkerBee;
+// mark.name correspond à ''
+// mark.dept correspond à 'général'
+// mark.projects correspond à []
-<pre class="brush: js">marc.nom = "";
-marc.branche = "commun";
-marc.projets = [];
+let fred = new SalesPerson;
+// fred.name correspond à ''
+// fred.dept correspond à 'ventes'
+// fred.projects correspond à []
+// fred.quota correspond à 100
+
+let jane = new Engineer;
+// jane.name correspond à ''
+// jane.dept correspond à 'ingénierie'
+// jane.projects correspond à []
+// jane.machine correspond à ''
</pre>
-<p>L’objet <code>marc</code> hérite des valeurs des propriétés <code>nom</code> et <code>branche</code> via le constructeur <code>Employé</code>. Il y a une valeur locale pour la propriété <code>projets</code> grâce au constructeur <code>Travailleur</code>.</p>
+<h2 id="object_properties">Les propriétés d'un objet</h2>
-<p>Ces constructeurs ne permettent pas de fournir des valeurs spécifiques, l’information créée est générique pour chaque objet. Les valeurs des propriétés sont celles par défaut, comme pour tous les autres objets créés à partir de <code>Travailleur</code>. On peut, bien sûr, changer les valeurs de ces propriétés pour fournir des valeurs spécifiques :</p>
+<p>Cette section explique comment les objets héritent des propriétés d'autres objets dans la chaîne des prototypes et ce qui se passe lorsque vous ajoutez une propriété au moment de l'exécution.</p>
-<pre class="brush: js">marc.nom = "Marc Dupont";
-marc.branche = "admin";
-marc.projets = ["navigateur"];</pre>
+<h3 id="inheriting_properties">L'héritage de propriétés</h3>
-<h3 id="L’ajout_de_propriétés">L’ajout de propriétés</h3>
+<p>Supposons que vous créez l'objet <code>mark</code> comme un <code>WorkerBee</code> avec l'instruction suivante :</p>
-<p>En JavaScript, on peut ajouter des propriétés lors de l’exécution et on peut utiliser des propriétés qui ne seraient pas définies par le constructeur. Afin d’ajouter une propriété à un objet donné, on assigne une valeur de la façon suivante :</p>
+<pre class="brush: js">let mark = new WorkerBee;</pre>
-<pre class="brush: js">marc.bonus = 3000;
-</pre>
+<p>Lorsque JavaScript voit l'opérateur <code>new</code>, il crée un nouvel objet générique et définit implicitement la valeur de la propriété interne [[Prototype]] à la valeur de <code>WorkerBee.prototype</code> et passe ce nouvel objet comme valeur du mot-clé <em><code>this</code></em> à la fonction du constructeur <code>WorkerBee</code>. La propriété interne [[Prototype]] détermine la chaîne de prototypes utilisée pour retourner les valeurs des propriétés. Une fois ces propriétés définies, JavaScript renvoie le nouvel objet et l'instruction d'affectation définit la variable <code>mark</code> à cet objet.</p>
-<p>Désormais, l’objet <code>marc</code> possède la propriété <code>bonus</code>. En revanche, aucun autre <code>Travailleur</code> ne possède cette propriété.</p>
+<p>Ce processus ne met pas explicitement des valeurs dans l'objet <code>mark</code> (valeurs <em>locales</em>) pour les propriétés que <code>mark</code> hérite de la chaîne de prototypes. Lorsque vous demandez la valeur d'une propriété, JavaScript vérifie d'abord si la valeur existe dans cet objet. Si c'est le cas, cette valeur est retournée. Si la valeur n'existe pas localement, JavaScript vérifie la chaîne des prototypes (en utilisant la propriété interne [[Prototype]]). Si un objet de la chaîne des prototypes possède une valeur pour la propriété, cette valeur est renvoyée. Si aucune propriété de ce type n'est trouvée, JavaScript indique que l'objet ne possède pas la propriété. Ainsi, l'objet <code>mark</code> possède les propriétés et valeurs suivantes :</p>
-<p>Si on ajoute une nouvelle propriété à un objet qui est utilisé comme prototype pour un constructeur, alors tous les objets créés à partir de ce constructeur bénéficieront de cette propriété grâce à l’héritage. Ainsi, on peut ajouter une propriété <code>spécialité</code> à tous les employés grâce à l’instruction suivante :</p>
+<pre class="brush: js">mark.name = '';
+mark.dept = 'général';
+mark.projects = [];</pre>
-<pre class="brush: js">Employé.prototype.spécialité = "aucune";
-</pre>
+<p>L'objet <code>mark</code> se voit attribuer des valeurs locales pour les propriétés <code>name</code> et <code>dept</code> par le constructeur <code>Employee</code>. Une valeur locale lui est attribuée pour la propriété <code>projects</code> par le constructeur <code>WorkerBee</code>. On obtient ainsi l'héritage des propriétés et de leurs valeurs en JavaScript. Certaines subtilités de ce processus sont abordées dans <a href="#property_inheritance_revisited">L'héritage des propriétés, revisité</a>.</p>
-<p>Dès que l’instruction est exécutée par JavaScript, l’objet <code>marc</code> possèdera aussi la propriété <code>spécialité</code> initialisée avec la valeur <code>"aucune"</code>. Le schéma suivant décrit l’effet de cet ajout puis de la surcharge de cette propriété pour le prototype <code>Ingénieur</code>.</p>
+<p>Comme ces constructeurs ne vous permettent pas de fournir des valeurs spécifiques à une instance, ces informations sont génériques. Les valeurs des propriétés sont celles par défaut partagées par tous les nouveaux objets créés à partir de <code>WorkerBee</code>. Vous pouvez, bien sûr, modifier les valeurs de n'importe laquelle de ces propriétés. Ainsi, vous pourriez donner des informations spécifiques pour <code>mark</code> comme suit :</p>
-<p><img alt="" class="internal" src="/@api/deki/files/4422/=figure8.4.png" style="height: 519px; width: 833px;"><br>
- <small><strong>Ajouter des propriétés</strong></small></p>
+<pre class="brush: js">mark.name = 'Mark Eting';
+mark.dept = 'admin';
+mark.projects = ['navigateur'];</pre>
-<h2 id="Des_constructeurs_plus_flexibles">Des constructeurs plus flexibles</h2>
+<h3 id="adding_properties">L'ajout de propriétés</h3>
-<p>Les fonctions constructeur utilisées jusqu’à présent ne permettaient pas de définir les valeurs des propriétés à la création d’une instance. De la même façon qu’en Java, il est possible d’utiliser des arguments pour ces fonctions afin d’initialiser les valeurs des propriétés des instances.</p>
+<p>En JavaScript, vous pouvez ajouter des propriétés à tout objet au moment de l'exécution. Vous n'êtes pas contraint d'utiliser uniquement les propriétés fournies par la fonction du constructeur. Pour ajouter une propriété spécifique à un seul objet, vous attribuez une valeur à l'objet, comme suit :</p>
-<p><img alt="" class="internal" id="figure8.5" src="/@api/deki/files/4423/=figure8.5.png" style="height: 481px; width: 1012px;"><br>
- <small><strong>Définir les propriétés grâce au constructeur</strong></small></p>
+<pre class="brush: js">mark.bonus = 3000;</pre>
-<p>Le tableau suivant montre les définitions de ces objets en JavaScript et en Java.</p>
+<p>Maintenant, l'objet <code>mark</code> possède une propriété <code>bonus</code>, mais aucun autre objet <code>WorkerBee</code> ne possède cette propriété.</p>
-<table>
- <thead>
- <tr>
- <th scope="col">JavaScript</th>
- <th scope="col">Java</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <pre class="brush: js">
-function Employé (nom, branche) {
- this.nom = nom || "";
- this.branche = branche || "commun";
-}
-</pre>
- </td>
- <td>
- <pre class="brush: java">
-public class Employé {
- public String nom;
- public String branche;
- public Employé () {
- this("", "commun");
- }
- public Employé (String nom) {
- this(nom, "commun");
- }
- public Employé (String nom, String branche) {
- this.nom = nom;
- this.branche = branche;
- }
-}
-</pre>
- </td>
- </tr>
- <tr>
- <td>
- <pre class="brush: js">
-function Travailleur (projs) {
- this.projets = projs || [];
+<p>Si vous ajoutez une nouvelle propriété à un objet qui est utilisé comme prototype pour une fonction du constructeur, vous ajoutez cette propriété à tous les objets qui héritent des propriétés du prototype. Par exemple, vous pouvez ajouter une propriété <code>specialty</code> à tous les employés avec l'instruction suivante :</p>
+
+<pre class="brush: js">Employee.prototype.specialty = 'aucune';</pre>
+
+<p>Dès que JavaScript exécute cette instruction, l'objet <code>mark</code> possède également la propriété <code>specialty</code> avec la valeur <code>"aucune"</code>. La figure suivante montre l'effet de l'ajout de cette propriété au prototype <code>Employee</code>, puis de sa surcharge pour le prototype <code>Engineer</code>.</p>
+
+<p><img alt="Ajout de propriétés" src="figure8.4.png"></p>
+
+<h2 id="more_flexible_constructors">Des constructeurs plus flexibles</h2>
+
+<p>Les fonctions correctrices présentées jusqu'à présent ne vous permettent pas de spécifier les valeurs des propriétés lorsque vous créez une instance. Comme avec Java, vous pouvez fournir des arguments aux constructeurs pour initialiser les valeurs des propriétés des instances. La figure suivante montre une façon de le faire.</p>
+
+<p><img alt="Spécifier des propriétés dans un constructeur, prise 1" src="figure8.5.png"></p>
+
+<p>Les paires d'exemples suivantes montrent les définitions Java et JavaScript de ces objets.</p>
+
+<pre class="brush: js">// JavaScript
+function Employee(name, dept) {
+ this.name = name || ''; // L'argument donné OU la valeur par défaut
+ this.dept = dept || 'général'; // L'argument donné OU la valeur par défaut
+}</pre>
+
+<pre class="brush: java">// Java
+public class Employee {
+ public String name;
+ public String dept;
+ // On assigne les valeurs par défaut aux propriétés
+ public Employee () {
+ this("", "général");
+ }
+ // On assigne une valeur donnée et une par défaut aux propriétés
+ public Employee (String name) {
+ this(name, "général");
+ }
+ // On assigne les deux arguments donnés aux propriétés
+ public Employee (String name, String dept) {
+ this.name = name;
+ this.dept = dept;
+ }
+}</pre>
+
+<pre class="brush: js">// JavaScript
+function WorkerBee(projs) {
+ this.projects = projs || []; // L'argument donné OU la valeur par défaut
}
-Travailleur.prototype = new Employé;
-</pre>
- </td>
- <td>
- <pre class="brush: java">
-public class Travailleur extends Employé {
- public String[] projets;
- public Travailleur () {
+WorkerBee.prototype = new Employee;</pre>
+
+<pre class="brush: java">// Java
+public class WorkerBee extends Employee {
+ public String[] projects;
+ // On assigne une valeur par défaut à la propriété
+ public WorkerBee () {
this(new String[0]);
}
- public Travailleur (String[] projs) {
- this.projets = projs;
+ // On assigne l'argument donné à la propriété
+ public WorkerBee (String[] projs) {
+ projects = projs;
}
-}
+}</pre>
-</pre>
- </td>
- </tr>
- <tr>
- <td>
- <pre class="brush: js">
-
-function Ingénieur (moteur) {
- this.branche = "ingénierie";
- this.moteur = moteur || "";
+<pre class="brush: js">// JavaScript
+function Engineer(mach) {
+ this.dept = 'engineering'; // On réécrit la valeur de « dept »
+ this.machine = mach || ''; // L'argument donné OU la valeur par défaut
}
-Ingénieur.prototype = new Travailleur;
-</pre>
- </td>
- <td>
- <pre class="brush: java">
-public class Ingénieur extends Travailleur {
- public String moteur;
- public Ingénieur () {
- this.branche = "ingénierie";
- this.moteur = "";
+Engineer.prototype = new WorkerBee;</pre>
+
+<pre class="brush: java">// Java
+public class Engineer extends WorkerBee {
+ public String machine;
+ public Engineer () {
+ dept = "engineering"; // On réécrit la valeur de « dept »
+ machine = ""; // On assigne une valeur par défaut à la propriété
}
- public Ingénieur (String moteur) {
- this.branche = "ingénierie";
- this.moteur = moteur;
+ public Engineer (String mach) {
+ dept = "engineering"; // On réécrit la valeur de « dept »
+ machine = mach; // On assigne l'argument donné à la propriété
}
-}
-</pre>
- </td>
- </tr>
- </tbody>
-</table>
+}</pre>
-<p>Les définitions JavaScript présentées ci-dessus utilisent une instruction qui peut paraître étrange pour avoir des valeurs par défaut :</p>
+<p>Ces définitions JavaScript utilisent un idiome spécial pour définir les valeurs par défaut :</p>
-<pre class="brush: js">this.nom = nom || "";
-</pre>
+<pre class="brush: js">this.nom = nom || "";</pre>
-<p>L’opérateur correspondant au OU logique en JavaScript (||) évalue le premier argument. Si cet argument peut être converti en <code>true</code>, alors l’opérateur renverra cet argument. Sinon, il renvoie la valeur du second argument. Ainsi, en utilisant ce code, on teste si la valeur fournie (<code>nom</code>) est utile ou non : si c’est le cas, on l’utilise pour la propriété, sinon on conserve la valeur par défaut (ici la chaîne vide). Cet exemple peut paraître déroutant mais permet d’être plus concis.</p>
+<p>L'opérateur logique OU de JavaScript (<code>||</code>) évalue son premier argument. Si cet argument se transforme en vrai, l'opérateur le retourne. Sinon, l'opérateur renvoie la valeur du deuxième argument. Par conséquent, cette ligne de code teste pour voir si <code>name</code> a une valeur utile pour la propriété <code>name</code>. Si c'est le cas, elle définit <code>this.name</code> à cette valeur. Sinon, elle définit <code>this.name</code> à la chaîne de caractères vide. Ce chapitre utilise cet idiome par souci de concision ; cependant, il peut être déroutant au premier abord.</p>
<div class="note">
-<p>Attention, cela peut ne pas fonctionner comme souhaité si le constructeur est appelé avec des arguments qui seront convertis à <code><code>false</code></code> (comme <code>0</code> (zéro) et la chaîne de caractère vide (<code><code>""</code></code>). Si ces valeurs sont utilisées, la valeur par défaut sera prise en compte.</p>
+ <p><strong>Note :</strong> Cela peut ne pas fonctionner comme prévu si la fonction du constructeur est appelée avec des arguments qui se convertissent en <code>false</code> (comme <code>0</code> (zéro) et la chaîne vide (<code>""</code>)). Dans ce cas, la valeur par défaut sera choisie.</p>
</div>
-<p>Grâce à ces définitions, on peut créer une instance d’un objet en utilisant des valeurs spécifiques pour les propriétés. On peut par exemple utiliser :</p>
+<p>Avec ces définitions, lorsque vous créez une instance d'un objet, vous pouvez spécifier des valeurs pour les propriétés définies localement. Vous pouvez utiliser l'instruction suivante pour créer un nouvel <code>Engineer</code> :</p>
-<pre class="brush: js">var jeanne = new Ingénieur("carnot");</pre>
+<pre class="brush: js">let jane = new Engineer('belau');</pre>
-<p>Les propriétés de l’objet sont donc désormais :</p>
+<p>Les propriétés de <code>Jane</code> sont maintenant :</p>
-<pre class="brush: js">jeanne.nom == "";
-jeanne.branche == "ingénierie";
-jeanne.projets == [];
-jeanne.moteur == "carnot"
-</pre>
+<pre class="brush: js">jane.name == '';
+jane.dept == 'engineering';
+jane.projects == [];
+jane.machine == 'belau';</pre>
-<p>On peut remarquer qu’avec ces définitions, on ne peut pas définir de valeur initiale pour les propriétés provenant de l’héritage, comme <code>nom</code> ici. Si on souhaite définir des valeurs initiales pour ces propriétés, il faut modifier légèrement le constructeur.</p>
+<p>Remarquez qu'avec ces définitions, vous ne pouvez pas spécifier une valeur initiale pour une propriété héritée telle que <code>name</code>. Si vous voulez spécifier une valeur initiale pour les propriétés héritées en JavaScript, vous devez ajouter du code supplémentaire à la fonction du constructeur.</p>
-<p>Jusqu’à présent, le constructeur utilisé permettait de créer un objet générique puis de créer des propriétés et de spécifier leurs valeurs pour le nouvel objet. On peut utiliser un constructeur afin de définir des valeurs spécifiques pour les autres propriétés plus hautes dans l’héritage. Pour ce faire, on appelle le constructeur de l’objet plus haut dans l’héritage au sein même du constructeur de l’objet courant.</p>
+<p>Jusqu'à présent, la fonction du constructeur a créé un objet générique, puis a spécifié les propriétés et valeurs locales du nouvel objet. Vous pouvez demander au constructeur d'ajouter d'autres propriétés en appelant directement la fonction du constructeur d'un objet situé plus haut dans la chaîne des prototypes. La figure suivante montre ces nouvelles définitions.</p>
-<p><img alt="" class="internal" src="/@api/deki/files/4430/=figure8.6.png" style="height: 534px; width: 1063px;"><br>
- <small><strong>La définition de propriétés héritées dans un constructeur</strong></small></p>
+<p><img alt="Spécifier des propriétés dans un constructeur, prise 2" src="figure8.6.png"></p>
-<p>Ainsi, le constructeur de <code>Ingénieur</code> sera :</p>
+<p>Examinons l'une de ces définitions en détails. Voici la nouvelle définition pour le constructeur <code>Engineer</code> :</p>
-<pre class="brush: js">function Ingénieur (nom, projets, moteur) {
- this.base = Travailleur;
- this.base(nom, "ingénierie", projets);
- this.moteur = moteur || "";
-}
-</pre>
+<pre class="brush: js">function Engineer(name, projs, mach) {
+ this.base = WorkerBee;
+ this.base(name, 'ingénierie', projs);
+ this.machine = mach || '';
+}</pre>
-<p>Si on crée ensuite un objet <code>Ingénieur</code> de cette façon :</p>
+<p>Supposons que vous créez un nouvel objet <code>Engineer</code> comme suit :</p>
-<pre class="brush: js">var jeanne = new Ingénieur("Jeanne Dubois", ["navigateur", "javascript"], "carnot");
+<pre class="brush: js">let jane = new Engineer('Jane Dupont', ['navigateur', 'javascript'], 'belau');
</pre>
-<p>L’exécution du code entraînera les étapes suivantes :</p>
+<p>JavaScript suit les étapes suivantes :</p>
<ol>
- <li>La création d’un objet générique avec l'opérateur <code>new</code> qui assigne la valeur <code>Ingénieur.prototype</code> à la propriété <code>__proto__</code>.</li>
- <li>L'opérateur <code>new</code> passe ensuite l’objet au constructeur <code>Ingénieur</code> comme valeur du mot-clé <code>this</code>.</li>
- <li>Le constructeur crée une nouvelle propriété, appelée <code>base</code>, pour cet objet. Cette propriété reçoit la valeur du constructeur <code>Travailleur</code>. Ainsi le constructeur <code>Travailleur</code> devient une méthode de l’objet <code>Ingénieur</code>. Le nom de cette propriété <code>base</code> n’est pas spécial, on pourrait utiliser un autre nom pour cette propriété (sous réserve qu’il soit valide).</li>
- <li>
- <p>Le constructeur appelle la méthode <code>base</code> et lui passe deux arguments qui avaient été passés (<code>"Jeanne Dubois"</code> et <code>["navigateur", "javascript"]</code>), ainsi que la chaîne de caractères <code>"ingénierie"</code>. Le fait d’utiliser <code>"ingénierie"</code> explicitement indique que tous les objets <code>Ingénieur</code> auront la même valeur pour la propriété <code>branche</code> qui aura été héritée. Cela permet également de surcharger la valeur par défaut héritée de <code>Employé</code>.</p>
- </li>
- <li>
- <p><code>base</code> étant une méthode d'<code>Ingénieur</code>, lors de l'appel de cette fonction, le mot clé <code>this</code> aura été lié à l'objet créé en 1. Ainsi, la fonction <code>Travailleur</code> passera les arguments <code>"Jeanne Dubois"</code> et <code>"ingénierie"</code> au constructeur <code>Employé</code>. Une fois que la fonction constructeur <code>Employé</code> a renvoyé un résultat, la fonction <code>Travailleur</code> utilise l'argument restant pour donner la valeur à la propriété <code>projets</code>.</p>
- </li>
- <li>Une fois que la méthode <code>base</code> a renvoyé un résultat, le constructeur <code>Ingénieur</code> initialise la propriété <code>moteur</code> avec la valeur <code>"carnot"</code>.</li>
- <li>Lorsque le constructeur renvoie le résultat, il est assigné à la variable <code>jeanne</code>.</li>
+ <li>L'opérateur <code>new</code> crée un objet générique et définit sa propriété <code>__proto__</code> à <code>Engineer.prototype</code>.</li>
+ <li>L'opérateur <code>new</code> transmet le nouvel objet au constructeur <code>Engineer</code> comme valeur du mot clé <code>this</code>.</li>
+ <li>Le constructeur crée une nouvelle propriété appelée <code>base</code> pour cet objet et affecte la valeur du constructeur <code>WorkerBee</code> à la propriété <code>base</code>. Cela fait du constructeur <code>WorkerBee</code> une méthode de l'objet <code>Engineer</code>. Le nom de la propriété <code>base</code> n'est pas spécial. Vous pouvez utiliser n'importe quel nom de propriété légal ; <code>base</code> est évocateur de son but.</li>
+ <li>Le constructeur appelle la méthode <code>base</code>, en passant comme arguments deux des arguments passés au constructeur (<code>"Jane Dupont"</code> et <code>["navigateur", "javascript"]</code>) et également la chaîne <code>"ingénierie"</code>. L'utilisation explicite de <code>"ingénierie"</code> dans le constructeur indique que tous les objets <code>Engineer</code> ont la même valeur pour la propriété <code>dept</code> héritée, et cette valeur remplace la valeur héritée de <code>Employee</code>.</li>
+ <li>Parce que <code>base</code> est une méthode de <code>Engineer</code>, dans l'appel à <code>base</code>, JavaScript lie le mot-clé <code>this</code> à l'objet créé à l'étape 1. Ainsi, la fonction <code>WorkerBee</code> transmet à son tour les arguments <code>"Jane Dupont"</code> et <code>"ingénierie"</code> à la fonction du constructeur <code>Employee</code>. Au retour de la fonction du constructeur <code>Employee</code>, la fonction <code>WorkerBee</code> utilise l'argument restant pour définir la propriété <code>projects</code>.</li>
+ <li>Au retour de la méthode <code>base</code>, le constructeur <code>Engineer</code> initialise la propriété <code>machine</code> de l'objet à <code>"belau"</code>.</li>
+ <li>Au retour du constructeur, JavaScript affecte le nouvel objet à la variable <code>jane</code>.</li>
</ol>
-<p>On peut penser qu’un simple appel au constructeur <code>Travailleur</code>, dans le constructeur <code>Ingénieur</code> permette de définir l'héritage pour les objets <code>Ingénieur</code>. Attention, ce n’est pas le cas. Un simple appel au constructeur <code>Travailleur</code> permet de bien définir les valeurs des propriétés spécifiées dans les constructeurs appelés. En revanche, si plus tard on souhaite ajouter des propriétés aux prototypes <code>Employé</code> ou <code>Travailleur</code> : l'objet <code>Ingénieur</code> n’en héritera pas. Si par exemple on a :</p>
+<p>Vous pourriez penser que, ayant appelé le constructeur <code>WorkerBee</code> à partir de l'intérieur du constructeur <code>Engineer</code>, vous avez mis en place l'héritage de manière appropriée pour les objets <code>Engineer</code>. Ce n'est pas le cas. L'appel du constructeur <code>WorkerBee</code> garantit qu'un objet <code>Engineer</code> commence avec les propriétés spécifiées dans toutes les fonctions des constructeurs qui sont appelées. Cependant, si vous ajoutez ultérieurement des propriétés aux prototypes <code>Employee</code> ou <code>WorkerBee</code>, ces propriétés ne sont pas héritées par l'objet <code>Engineer</code>. Par exemple, supposons que vous ayez les déclarations suivantes :</p>
-<pre class="brush: js">function Ingénieur (nom, projets, moteur) {
- this.base = Travailleur;
- this.base(nom, "ingénierie", projets);
- this.moteur = moteur || "";
+<pre class="brush: js">function Engineer(name, projs, mach) {
+ this.base = WorkerBee;
+ this.base(name, 'ingénierie', projs);
+ this.machine = mach || '';
}
-var jeanne = new Ingénieur("Jeanne Dubois", ["navigateur", "javascript"], "carnot");
-Employé.prototype.spécialité = "aucune";
-</pre>
-<p>L'objet <code>jeanne</code> n’héritera pas de la propriété <code>spécialité</code>. Il aurait fallu préciser le prototype pour s'assurer de l'héritage dynamique. Si on a plutôt :</p>
+let jane = new Engineer('Jane Dupont', ['navigateur', 'javascript'], 'belau');
+Employee.prototype.specialty = 'aucune';</pre>
-<pre class="brush: js">function Ingénieur (nom, projets, moteur) {
- this.base = Travailleur;
- this.base(nom, "ingénierie", projets);
- this.moteur = moteur || "";
+<p>L'objet <code>jane</code> n'hérite pas de la propriété <code>specialty</code>. Vous devez encore configurer explicitement le prototype pour assurer un héritage dynamique. Supposons plutôt que vous ayez ces déclarations :</p>
+
+<pre class="brush: js">function Engineer(name, projs, mach) {
+ this.base = WorkerBee;
+ this.base(name, 'ingénierie', projs);
+ this.machine = mach || '';
}
-Ingénieur.prototype= new Travailleur;
-var jeanne = new Ingénieur("Jeanne Dubois", ["navigateur", "javascript"], "carnot");
-Employé.prototype.spécialité = "aucune";
-</pre>
-<p>Alors la valeur de la propriété <code>spécialité</code> de <code>jeanne</code> sera "aucune".</p>
+Engineer.prototype = new WorkerBee;
+let jane = new Engineer('Jane Dupont', ['navigateur', 'javascript'], 'belau');
+Employee.prototype.specialty = 'aucune';</pre>
-<p>Une autre façon d’utiliser l’héritage dans un constructeur peut être d'utiliser les méthodes <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/call"><code>call()</code></a> et <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/apply"><code>apply()</code></a>. Les deux fragments de codes présentés ici sont équivalents :</p>
+<p>Maintenant la valeur de la propriété <code>jane</code> de l'objet <code>specialty</code> est « aucune ».</p>
-<table>
- <tbody>
- <tr>
- <td>
- <pre class="brush: js">
-function Ingénieur (nom, projets, moteur) {
- this.base = Travailleur;
- this.base(nom, "ingénierie", projets);
- this.moteur = moteur || "";
-}
-</pre>
- </td>
- <td>
- <pre class="brush: js">
-function Ingénieur (nom, projets, moteur) {
- Travailleur.call(this, nom, "ingénierie", projets);
- this.moteur = moteur || "";
-}
-</pre>
- </td>
- </tr>
- </tbody>
-</table>
+<p>Une autre façon d'hériter est d'utiliser les méthodes <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a></code> / <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/apply"><code>apply()</code></a>. Les méthodes ci-dessous sont équivalentes :</p>
+
+<pre class="brush: js">function Engineer(name, projs, mach) {
+ this.base = WorkerBee;
+ this.base(name, 'ingénierie', projs);
+ this.machine = mach || '';
+}</pre>
+
+<pre class="brush: js">function Engineer(name, projs, mach) {
+ WorkerBee.call(this, name, 'ingénierie', projs);
+ this.machine = mach || '';
+}</pre>
-<p>En utilisant la méthode <code>call()</code> on obtient une syntaxe plus claire car on n’utilise plus la propriété intermédiaire <code>base</code>.</p>
+<p>L'utilisation de la méthode JavaScript <code>call()</code> rend une implémentation plus propre car <code>base</code> n'est plus nécessaire.</p>
-<h2 id="L’héritage_de_propriétés_les_subtilités">L’héritage de propriétés : les subtilités</h2>
+<h2 id="property_inheritance_revisited">L'héritage des propriétés, revisité</h2>
-<p>Les sections précédentes ont permis de décrire le fonctionnement des constructeurs et des prototypes, notamment par rapport aux hiérarchies d’objets et à l’héritage. L’objectif de cette section est de couvrir un peu plus en profondeur certaines facettes de l'héritage qui n’étaient pas détaillées avant.</p>
+<p>Les sections précédentes ont décrit comment les constructeurs et prototypes JavaScript fournissent des hiérarchies et de l'héritage. Cette section aborde certaines subtilités qui n'étaient pas nécessairement apparentes dans les discussions précédentes.</p>
-<h3 id="Valeurs_locales_et_valeurs_héritées">Valeurs locales et valeurs héritées</h3>
+<h3 id="local_versus_inherited_values">Valeurs locales et valeurs héritées</h3>
-<p>Quand on accède à la propriété d’un objet, JavaScript effectue les étapes suivantes :</p>
+<p>Lorsque vous accédez à une propriété d'objet, JavaScript effectue les étapes suivantes, comme décrit précédemment dans ce chapitre :</p>
<ol>
- <li>On vérifie si la valeur existe localement : si c'est le cas on renvoie cette valeur.</li>
- <li>S'il n’y a pas de valeur locale, on parcourt la chaîne des prototypes grâce à la propriété<code>__proto__</code>.</li>
- <li>Si un objet de la chaîne de prototypes possède une valeur pour la propriété recherchée, alors on renvoie cette valeur.</li>
- <li>Si aucune propriété correspondante n’est trouvée, alors l’objet ne possède pas cette propriété.</li>
+ <li>Vérifiez si la valeur existe localement. Si c'est le cas, elle est retournée.</li>
+ <li>S'il n'y a pas de valeur locale, vérifiez la chaîne de prototypes (en utilisant la propriété <code>__proto__</code>).</li>
+ <li>Si un objet de la chaîne de prototypes possède une valeur pour la propriété spécifiée, renvoyer cette valeur.</li>
+ <li>Si aucune propriété de ce type n'est trouvée, l'objet ne possède pas cette propriété.</li>
</ol>
-<p>L'issue de cet algorithme peut dépendre de la façon dont on a défini au fur et à mesure les différents objets. Dans l'exemple initial on avait les définitions :</p>
+<p>Le résultat de ces étapes dépend de la façon dont vous définissez les choses en cours de route. L'exemple original avait ces définitions :</p>
-<pre class="brush: js">function Employé () {
- this.nom = "";
- this.branche = "commun";
+<pre class="brush: js">function Employee() {
+ this.name = '';
+ this.dept = 'général';
}
-function Travailleur () {
- this.projets = [];
+function WorkerBee() {
+ this.projects = [];
}
-Travailleur.prototype = new Employé;
-</pre>
+WorkerBee.prototype = new Employee;</pre>
-<p>Si on utilise ces définitions et qu'on définit une instance de <code>Travailleur</code> appelée <code>amy</code> avec l'instruction suivante :</p>
+<p>Avec ces définitions, supposons que vous créez <code>amy</code> comme une instance de <code>WorkerBee</code> avec l'instruction suivante :</p>
-<pre class="brush: js">var amy = new Travailleur;
-</pre>
+<pre class="brush: js">let amy = new WorkerBee;</pre>
-<p>Alors l'objet <code>amy</code> possède une propriété locale : <code>projets</code>. Les valeurs des propriétés <code>nom</code> et <code>branche</code> ne sont pas locales, elles sont obtenues grâce à la propriété <code>__proto__</code> de l'objet amy. Ainsi <code>amy</code> possède les propriétés suivantes avec les valeurs respectives :</p>
+<p>L'objet <code>amy</code> possède une propriété locale, <code>projects</code>. Les valeurs des propriétés <code>name</code> et <code>dept</code> ne sont pas locales à <code>amy</code> et héritent donc dans la propriété <code>amy</code> de l'objet <code>__proto__</code>. Ainsi, <code>amy</code> possède ces valeurs de propriétés :</p>
-<pre class="brush: js">amy.nom == "";
-amy.branche == "commun";
-amy.projets == [];
-</pre>
+<pre class="brush: js">amy.name == '';
+amy.dept == 'général';
+amy.projects == [];</pre>
-<p>Si maintenant on change la valeur de la propriété <code>nom</code> pour le prototype associé à <code>Employé</code> :</p>
+<p>Supposons maintenant que vous modifiez la valeur de la propriété <code>name</code> dans le prototype associé à <code>Employee</code> :</p>
-<pre class="brush: js">Employé.prototype.nom = "Inconnu"
-</pre>
+<pre class="brush: js">Employee.prototype.name = 'Inconnu·e';</pre>
-<p>On pourrait penser que cette nouvelle valeur est propagée pour toutes les instances de <code>Employé</code>. Ce n’est pas le cas.</p>
+<p>À première vue, on pourrait s'attendre à ce que cette nouvelle valeur se propage vers le bas à toutes les instances de <code>Employee</code>. Cependant, ce n'est pas le cas.</p>
-<p>En effet, lorsqu’on crée n’importe quelle instance de <code>Employé</code>, cette instance obtient une valeur locale pour la propriété <code>nom</code> (qui est la chaîne de caractères vide). Cela signifie que lorsqu'on utilise le prototype <code>Travailleur</code> dans lequel on crée un nouvel objet <code>Employé</code>, <code>Travailleur.prototype</code> aura une valeur locale pour la propriété <code>nom</code>. Ainsi, quand JavaScript recherche la propriété <code>nom</code> de l'objet <code>amy</code> (qui est une instance de <code>Travailleur</code>), JavaScript trouve la valeur locale de cette propriété au niveau de <code>Travailleur.prototype</code> et ne remonte pas plus loin dans la chaîne : on n’atteint pas <code>Employé.prototype</code>.</p>
+<p>Lorsque vous créez <em>n'importe quelle</em> instance de l'objet <code>Employee</code>, cette instance obtient une <strong>valeur locale</strong> pour la propriété <code>name</code> (la chaîne de caractères vide). Cela signifie que lorsque vous définissez le prototype de <code>WorkerBee</code> en créant un nouvel objet <code>Employee</code>, <code>WorkerBee.prototype</code> a une valeur locale pour la propriété <code>name</code>. Par conséquent, lorsque JavaScript recherche la propriété <code>name</code> de l'objet <code>amy</code> (une instance de <code>WorkerBee</code>), JavaScript trouve la valeur locale de cette propriété dans <code>WorkerBee.prototype</code>. Il ne cherche donc pas plus haut dans la chaîne jusqu'à <code>Employee.prototype</code>.</p>
-<p>Si on souhaite changer la valeur de la propriété d’un objet pendant l’exécution et que sa valeur soit héritée par tous les descendants de l’objet, on ne peut pas définir cette propriété dans le constructeur de l'objet, il faut l’ajouter au constructeur du prototype associé. Si on change le code précédent par :</p>
+<p>Si vous souhaitez modifier la valeur d'une propriété d'un objet au moment de l'exécution et que la nouvelle valeur soit héritée par tous les descendants de l'objet, vous ne pouvez pas définir la propriété dans la fonction du constructeur de l'objet. Vous devez plutôt l'ajouter au prototype associé au constructeur. Par exemple, supposons que vous remplaciez le code précédent par le suivant :</p>
-<pre class="brush: js">function Employé () {
- this.branche = "commun"; // La propriété this.nom, qui est une variable locale, n'apparaît pas ici
+<pre class="brush: js">function Employee() {
+ this.dept = 'général'; // Notez que this.name (une variable locale) n'apparaît pas ici
}
-Employé.prototype.nom = ""; // Il s'agit d'une simple affectation
+Employee.prototype.name = ''; // Un seul exemplaire
-function Travailleur () {
- this.projets = [];
+function WorkerBee() {
+ this.projects = [];
}
-Travailleur.prototype = new Employé;
-
-var amy = new Travailleur;
-
-Employé.prototype.nom = "Inconnnu";
-</pre>
+WorkerBee.prototype = new Employee;
-<p>Alors on aura bien la propriété <code>nom</code> de <code>amy</code> qui deviendra "Inconnu".</p>
+let amy = new WorkerBee;
-<p>Comme on a pu le voir avec ces exemples, si on souhaite avoir des valeurs par défaut pour certaines propriétés et être capable de les modifier à l'exécution, il est nécessaire de les définir dans les propriétés du prototype du constructeur et non dans le constructeur même.</p>
+Employee.prototype.name = 'Inconnu·e';</pre>
-<h3 id="Comment_déterminer_les_relations_entre_les_instances">Comment déterminer les relations entre les instances</h3>
+<p>Dans ce cas, la propriété <code>name</code> de <code>amy</code> devient « Inconnu·e ».</p>
-<p>La recherche de propriétés JavaScript permet de rechercher parmi les propriétés de l’objet puis dans la propriété spéciale <code>__proto__</code> et ainsi de suite pour explorer la chaîne des prototypes.</p>
+<p>Comme le montrent ces exemples, si vous souhaitez définir des valeurs par défaut pour les propriétés d'un objet et que vous voulez pouvoir modifier ces valeurs au moment de l'exécution, vous devez définir les propriétés dans le prototype du constructeur, et non dans la fonction du constructeur elle-même.</p>
-<p>La propriété spéciale <code>__proto__</code> est défnie à la construction d'un objet et contient la valeur du constructeur de la propriété<code>prototype</code>. Ainsi, l’expression <code>new Toto()</code> crée un nouvel objet avec <code>__proto__ == <code class="moz-txt-verticalline">Toto.prototype</code></code>. Ainsi, tous les changements des propriétés de <code class="moz-txt-verticalline">Toto.prototype</code> sont propagés sur la chaîne des prototypes des objets ayant été créés par <code>new Toto()</code>.</p>
+<h3 id="determining_instance_relationships">Déterminer les relations entre les instances</h3>
-<p>Chaque objet (sauf <code>Object</code>) possède une propriété <code>__proto__</code>. Chaque fonction possède une propriété <code>prototype</code>. Ainsi, on peut relier les objets par « héritage prototypique ». Pour tester l’héritage, on peut comparer la propriété <code>__proto__</code> d'un objet avec la propriété <code>prototype</code> d'une fonction. JavaScript permet de faire ceci avec l’opérateur <code>instanceof</code> qui teste un objet par rapport à une fonction et qui renvoie true si l’objet hérite de la fonction prototype. Ainsi :</p>
+<p>La recherche de propriétés en JavaScript s'effectue dans les propriétés propres d'un objet et, si le nom de la propriété n'est pas trouvé, elle s'effectue dans la propriété spéciale de l'objet <code>__proto__</code>. Cette opération se poursuit de manière récursive ; le processus est appelé « recherche dans la chaîne des prototypes ».</p>
-<pre class="brush: js">var t = new Toto();
-var isTrue = (t instanceof Toto);</pre>
+<p>La propriété spéciale <code>__proto__</code> est définie lorsqu'un objet est construit ; elle prend la valeur de la propriété <code>prototype</code> du constructeur. Ainsi, l'expression <code>new Riri()</code> crée un objet avec <code>__proto__ == Riri.prototype</code>. Par conséquent, les modifications apportées aux propriétés de <code>Riri.prototype</code> modifient la recherche de propriétés pour tous les objets qui ont été créés par <code>new Riri()</code>.</p>
-<p>Pour avoir un exemple plus précis, si on crée un objet <code>Ingénieur</code> comme ceci :</p>
+<p>Chaque objet a une propriété <code>__proto__</code> (sauf <code>Object</code>) ; chaque fonction a une propriété <code>prototype</code>. Les objets peuvent donc être liés par « héritage de prototype » à d'autres objets. Vous pouvez tester l'héritage en comparant le <code>__proto__</code> d'un objet avec l'objet <code>prototype</code> d'une fonction. JavaScript fournit un raccourci : l'opérateur <code>instanceof</code> teste un objet par rapport à une fonction et renvoie vrai si l'objet hérite du prototype de la fonction. Par exemple,</p>
-<pre class="brush: js">var chris = new Engineer("Chris Pigman", ["jsd"], "fiji");
-</pre>
+<pre class="brush: js">let f = new Riri();
+let isTrue = (f instanceof Riri);</pre>
+
+<p>Pour un exemple plus détaillé, supposons que vous ayez le même ensemble de définitions que celui présenté dans <a href="#inheriting_properties">Héritage des propriétés</a>. Créez un objet <code>Engineer</code> comme suit :</p>
+
+<pre class="brush: js">let chris = new Engineer('Chris Anthème', ['jsd'], 'fiji');</pre>
-<p>L’ensemble des instructions suivantes renverra <code>true</code> :</p>
+<p>Avec cet objet, les affirmations suivantes sont toutes vraies :</p>
-<pre class="brush: js">chris.__proto__ == Ingénieur.prototype;
-chris.__proto__.__proto__ == Travailleur.prototype;
-chris.__proto__.__proto__.__proto__ == Employé.prototype;
+<pre class="brush: js">chris.__proto__ == Engineer.prototype;
+chris.__proto__.__proto__ == WorkerBee.prototype;
+chris.__proto__.__proto__.__proto__ == Employee.prototype;
chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
-chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
-</pre>
+chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;</pre>
-<p>On pourrait donc écrire la une fonction <code>instanceOf</code> de la façon suivante :</p>
+<p>Compte tenu de cela, vous pourriez écrire une fonction <code>instanceOf</code> comme suit :</p>
<pre class="brush: js">function instanceOf(object, constructor) {
+ object = object.__proto__;
while (object != null) {
if (object == constructor.prototype)
return true;
@@ -624,125 +564,122 @@ chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
object = object.__proto__;
}
return false;
-}
-</pre>
+}</pre>
-<div class="note"><strong>Note :</strong> L’implémentation ci-dessus possède un cas particulier pour le type d'objet "xml" : c'est une façon de traiter les objets XML et la façon dont ils sont représentés dans les versions plus récentes de JavaScript. N’hésitez pas à aller consulter la fiche {{bug(634150)}} si vous voulez en savoir plus.</div>
+<div class="note">
+ <p><strong>Note :</strong> L'implémentation ci-dessus vérifie le type de l'objet par rapport à « xml » afin de contourner une bizarrerie de la façon dont les objets XML sont représentés dans les versions récentes de JavaScript. Voir <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=634150">bug 634150</a> si vous voulez connaître les détails.</p>
+</div>
-<p class="note">Ainsi, avec cette fonction, les expressions suivantes seront vérifiées :</p>
+<p>En utilisant la fonction <code>instanceOf</code> définie ci-dessus, ces expressions sont vraies :</p>
-<pre class="brush: js">instanceOf (chris, Ingénieur)
-instanceOf (chris, Travailleur)
-instanceOf (chris, Employé)
-instanceOf (chris, Object)
-</pre>
+<pre class="brush: js">instanceOf(chris, Engineer)
+instanceOf(chris, WorkerBee)
+instanceOf(chris, Employee)
+instanceOf(chris, Object)</pre>
-<p>En revanche, l’expression qui suit est fausse :</p>
+<p>Mais l'expression suivante est fausse :</p>
-<pre class="brush: js">instanceOf (chris, Vendeur)
-</pre>
+<pre class="brush: js">instanceOf(chris, SalesPerson)</pre>
-<h3 id="Les_informations_globales_dans_les_constructeurs">Les informations globales dans les constructeurs</h3>
+<h3 id="global_information_in_constructors">Les informations globales dans les constructeurs</h3>
-<p>Lorsqu'on crée des constructeurs, on doit prendre des précautions si on souhaite manipuler des informations globales au sein d'un constructeur. Si, par exemple, on souhaite avoir un identifiant unique attribué automatiquement pour chaque nouvel employé, on pourrait utiliser la définition suivante :</p>
+<p>Lorsque vous créez des constructeurs, vous devez faire attention si vous définissez des informations globales dans le constructeur. Par exemple, supposons que vous souhaitez qu'un identifiant unique soit automatiquement attribué à chaque nouvel employé. Vous pourriez utiliser la définition suivante pour <code>Employee</code> :</p>
-<pre class="brush: js">var idCompteur = 1;
+<pre class="brush: js">let idCounter = 1; // On définit un compteur d'identifiant
-function Employé (nom, branche) {
- this.nom = nom || "";
- this.branche = branche || "commun";
- this.id = idCompteur++;
-}
-</pre>
+function Employee(name, dept) {
+ this.name = name || '';
+ this.dept = dept || 'général';
+ this.id = idCounter++; // On assigne la valeur et on incrémente le compteur
+}</pre>
-<p>Avec cette définition, si on utilise les instructions suivantes <code>victoria.id</code> sera 1 et <code>henri.id</code> sera 2:</p>
+<p>Avec cette définition, lorsque vous créez un nouvel <code>Employee</code>, le constructeur lui attribue l'ID suivant dans la séquence, puis incrémente le compteur d'ID global. Ainsi, si votre déclaration est la suivante, <code>victoria.id</code> vaut 1 et <code>harry.id</code> vaut 2 :</p>
-<pre class="brush: js">var victoria = new Employé("Victoria Rander", "international")
-var henri = new Employé("Henri Jelier", "ventes")
-</pre>
+<pre class="brush: js">let victoria = new Employee('Victoria Lamar', 'pubs');
+let harry = new Employee('Harry Stocrate', 'ventes');</pre>
-<p>De cette façon, on peut penser que cette solution convient. Cependant, <code>idCompteur</code> sera incrémenté à chaque fois qu’un objet <code>Employé</code> sera créé, quelqu’en soit la raison. Si on utilise la hiérarchie établie au cours de ce chapitre, le constructeur <code>Employé</code> sera appelé à chaque fois qu’on définit un prototype. Avec le code suivant par exemple :</p>
+<p>À première vue, cela semble correct. Cependant, <code>idCounter</code> est incrémenté à chaque fois qu'un objet <code>Employee</code> est créé, pour quelque raison que ce soit. Si vous créez toute la hiérarchie <code>Employee</code> présentée dans ce chapitre, le constructeur <code>Employee</code> est appelé chaque fois que vous mettez en place un prototype. Supposons que vous ayez le code suivant :</p>
-<pre class="brush: js">var idCompteur = 1;
+<pre class="brush: js">let idCounter = 1;
-function Employé (nom, branche) {
- this.nom = nom || "";
- this.branche = branche || "commun";
- this.id = idCompteur++;
+function Employee(name, dept) {
+ this.name = name || '';
+ this.dept = dept || 'général';
+ this.id = idCounter++;
}
-function Manager (nom, branche, rapports) {...}
-Manager.prototype = new Employé;
+function Manager(name, dept, reports) {...}
+Manager.prototype = new Employee;
-function Travailleur (nom, branche, projets) {...}
-Travailleur.prototype = new Employé;
+function WorkerBee(name, dept, projs) {...}
+WorkerBee.prototype = new Employee;
-function Ingénieur (nom, projets, moteur) {...}
-Ingénieur.prototype = new Travailleur;
+function Engineer(name, projs, mach) {...}
+Engineer.prototype = new WorkerBee;
-function Vendeur (nom, projets, quota) {...}
-Vendeur.prototype = new Travailleur;
+function SalesPerson(name, projs, quota) {...}
+SalesPerson.prototype = new WorkerBee;
-var alex = new Ingénieur("Alex S");
-</pre>
+let mac = new Engineer('Mac Fly');</pre>
-<p>Si on prend le cas où les définitions utilisent la propriété <code>base</code> et appellent le constructeur à chaque fois au-dessus, alors la propriété <code>alex.id</code> vaudra 3.</p>
+<p>Supposons en outre que les définitions omises ici possèdent la propriété <code>base</code> et appellent le constructeur situé au-dessus d'elles dans la chaîne des prototypes. Dans ce cas, au moment où l'objet <code>mac</code> est créé, <code>mac.id</code> est 5.</p>
-<p>Selon l’application qu’on a de cette information, on peut souhaiter ou non que ce compteur ne soit pas incrémenté avec ces étapes intermédiaires. Si on souhaite utiliser une valeur exacte, on pourra utiliser le constructeur suivant :</p>
+<p>Selon l'application, il peut être important ou non que le compteur ait été incrémenté ces fois supplémentaires. Si vous vous souciez de la valeur exacte de ce compteur, une solution possible consiste à utiliser plutôt le constructeur suivant :</p>
-<pre class="brush: js">function Employé (nom, branche) {
- this.nom = nom || "";
- this.branche = branche || "commun";
- if (nom)
- this.id = idCompteur++;
+<pre class="brush: js">function Employee(name, dept) {
+ this.name = name || '';
+ this.dept = dept || 'general';
+ // Ceci est une écriture raccourcie de l'opérateur if
+ // Si « name » est défini, alors on assigne et on incrémente
+ if (name) {
+ this.id = idCounter++;
+ }
}
</pre>
-<p>Lorsqu’on crée une instance d’<code>Employé</code> comme prototype, on ne fournit pas d’argument au constructeur. Ainsi, en utilisant ce constructeur, lorsqu’on ne fournit pas d’argument, le constructeur n’incrémente pas le compteur. De cette façon, pour qu’un employé ait un identifiant valide, il faut qu’on lui ait donné un nom. Avec cet exemple, <code>alex.id</code> vaudrait 1.</p>
+<p>Lorsque vous créez une instance de <code>Employee</code> pour l'utiliser comme prototype, vous ne fournissez pas d'arguments au constructeur. En utilisant cette définition du constructeur, lorsque vous ne fournissez pas d'arguments, le constructeur n'attribue pas de valeur à l'id et ne met pas à jour le compteur. Par conséquent, pour qu'un <code>Employee</code> obtienne un id, vous devez spécifier un nom pour l'employé. Dans cet exemple, <code>mac.id</code> serait 1.</p>
-<p>Une autre façon de procéder est de créer une copie du prototype d'<code>Employé</code> et d'affecter celle-ci à <code>Travailleur</code> :</p>
+<p>Vous pouvez également créer une copie de l'objet prototype de l'employé pour l'affecter à WorkerBee :</p>
-<pre class="brush: js">Travailleur.prototype = Object.create(Employé.prototype);
-// plutôt que Travailleur.prototype = new Employé;</pre>
+<pre class="brush: js">WorkerBee.prototype = Object.create(Employee.prototype);
+// au lieu de WorkerBee.prototype = new Employee</pre>
-<h3 id="L’absence_d’héritage_multiple">L’absence d’héritage multiple</h3>
+<h3 id="no_multiple_inheritance">Pas d'héritage multiple</h3>
-<p>Certains langages orientés objet permettent d’avoir un héritage multiple. Cela veut dire qu’un objet peut hériter des propriétés et des valeurs d’objets parents qui n’ont aucune relation. JavaScript ne permet pas d’avoir ce type d'héritage.</p>
+<p>Certains langages orientés objets permettent l'héritage multiple. C'est-à-dire qu'un objet peut hériter des propriétés et des valeurs d'objets parents non apparentés. JavaScript ne prend pas en charge l'héritage multiple.</p>
-<p>L’héritage des valeurs des propriétés s’effectue lors de l’exécution lorsque JavaScript explore la chaîne de prototype. Étant donné qu’un objet possède un seul prototype associé, JavaScript ne peut pas, dynamiquement, effectuer l’héritage sur plus d’une chaîne de prototypes.</p>
+<p>L'héritage des valeurs des propriétés se produit au moment de l'exécution, lorsque JavaScript recherche une valeur dans la chaîne de prototypes d'un objet. Comme un objet n'a qu'un seul prototype associé, JavaScript ne peut pas hériter dynamiquement de plus d'une chaîne de prototypes.</p>
-<p>En JavaScript, il est possible d’avoir un constructeur qui fait appel à plusieurs constructeurs. Cela donne en quelque sorte l’illusion d’un héritage multiple. Par exemple :</p>
+<p>En JavaScript, vous pouvez faire en sorte qu'une fonction de construction appelle plusieurs autres fonctions de construction en son sein. Cela donne l'illusion d'un héritage multiple. Par exemple, considérez les déclarations suivantes :</p>
-<pre class="brush: js">function Passioné (passion) {
- this.passion = passion || "plongée";
+<pre class="brush: js">function Hobbyist(hobby) {
+ this.hobby = hobby || 'plongée';
}
-function Ingénieur (nom, projets, moteur, passion) {
- this.base1 = Travailleur;
- this.base1(nom, "ingénierie", projets);
- this.base2 = Passioné;
- this.base2(passion);
- this.moteur = moteur || "";
+function Engineer(name, projs, mach, hobby) {
+ this.base1 = WorkerBee;
+ this.base1(name, 'ingénierie', projs);
+ this.base2 = Hobbyist;
+ this.base2(hobby);
+ this.machine = mach || '';
}
-Ingénieur.prototype = new Travailleur;
+Engineer.prototype = new WorkerBee;
-var denis = new Ingénieur("Denis Carle", ["collabra"], "carnot")
+let dennis = new Engineer('Dennis Ah', ['collaborateur'], 'hugo');
</pre>
-<p>Supposons que la définition de <code>Travailleur</code> soit utilisée plus haut dans ce chapitre. Dans ce cas, l’objet<code> dennis</code> aura les propriétés suivantes :</p>
+<p>Supposons en outre que la définition de <code>WorkerBee</code> soit celle utilisée précédemment dans ce chapitre. Dans ce cas, l'objet <code>dennis</code> possède ces propriétés :</p>
-<pre class="brush: js">denis.nom == "Denis Carle"
-denis.branche == "ingénierie"
-denis.projets == ["collabra"]
-denis.moteur == "carnot"
-denis.passion == "plongée"
-</pre>
+<pre class="brush: js">dennis.name == 'Dennis Ah';
+dennis.dept == 'ingénierie';
+dennis.projects == ['collaborateur'];
+dennis.machine == 'hugo';
+dennis.hobby == 'plongée';</pre>
-<p>On voit bien que <code>denis</code> bénéficie de la propriété <code>passion</code> du constructeur <code>Passioné</code>. Cependant, si, plus tard, on ajoute une propriété au prototype du constructeur :</p>
+<p>Donc <code>dennis</code> obtient bien la propriété <code>hobby</code> du constructeur <code>Hobbyist</code>. Cependant, supposons que vous ajoutez ensuite une propriété au prototype du constructeur <code>Hobbyist</code> :</p>
-<pre class="brush: js">Passioné.prototype.équipement = ["masque", "filet", "club", "balles"]
-</pre>
+<pre class="brush: js">Hobbyist.prototype.equipment = ['masque', 'palmes', 'régulateur', 'bcd'];</pre>
-<p>L’objet <code>denis</code> n’héritera pas de cette nouvelle propriété.</p>
+<p>L'objet <code>dennis</code> n'héritera pas de cette nouvelle propriété.</p>
-<p>{{PreviousNext("Web/JavaScript/Guide/Utiliser_les_objets", "Web/JavaScript/Guide/Utiliser_les_promesses")}}</p>
+<div>{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Using_promises")}}</div>