From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- files/fr/web/javascript/guide/apropos/index.html | 138 +++ .../guide/boucles_et_it\303\251ration/index.html" | 349 ++++++++ .../guide/collections_avec_cl\303\251s/index.html" | 152 ++++ .../guide/collections_index\303\251es/index.html" | 425 ++++++++++ .../index.html" | 408 +++++++++ .../expressions_et_op\303\251rateurs/index.html" | 934 +++++++++++++++++++++ .../assertions/index.html" | 106 +++ .../classes_de_caract\303\250res/index.html" | 182 ++++ .../groupes_et_intervalles/index.html" | 93 ++ .../index.html" | 745 ++++++++++++++++ .../limites/index.html" | 95 +++ .../quantificateurs/index.html" | 97 +++ .../index.html" | 430 ++++++++++ files/fr/web/javascript/guide/fonctions/index.html | 670 +++++++++++++++ .../javascript/guide/formatage_du_texte/index.html | 255 ++++++ files/fr/web/javascript/guide/index.html | 136 +++ .../web/javascript/guide/introduction/index.html | 135 +++ .../guide/iterateurs_et_generateurs/index.html | 175 ++++ .../guide/javascript_overview/index.html | 117 +++ .../index.html" | 747 ++++++++++++++++ .../index.html" | 78 ++ files/fr/web/javascript/guide/modules/index.html | 432 ++++++++++ .../guide/m\303\251taprogrammation/index.html" | 278 ++++++ .../javascript/guide/nombres_et_dates/index.html | 387 +++++++++ .../index.html" | 898 ++++++++++++++++++++ .../guide/retours_sur_h\303\251ritage/index.html" | 87 ++ .../javascript/guide/types_et_grammaire/index.html | 709 ++++++++++++++++ .../guide/utiliser_le_json_natif/index.html | 99 +++ .../guide/utiliser_les_objets/index.html | 474 +++++++++++ .../guide/utiliser_les_promesses/index.html | 314 +++++++ .../index.html" | 264 ++++++ 31 files changed, 10409 insertions(+) create mode 100644 files/fr/web/javascript/guide/apropos/index.html create mode 100644 "files/fr/web/javascript/guide/boucles_et_it\303\251ration/index.html" create mode 100644 "files/fr/web/javascript/guide/collections_avec_cl\303\251s/index.html" create mode 100644 "files/fr/web/javascript/guide/collections_index\303\251es/index.html" create mode 100644 "files/fr/web/javascript/guide/contr\303\264le_du_flux_gestion_des_erreurs/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_et_op\303\251rateurs/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/assertions/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/classes_de_caract\303\250res/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/groupes_et_intervalles/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/limites/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/quantificateurs/index.html" create mode 100644 "files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/\303\251chappement_propri\303\251t\303\251s_unicode/index.html" create mode 100644 files/fr/web/javascript/guide/fonctions/index.html create mode 100644 files/fr/web/javascript/guide/formatage_du_texte/index.html create mode 100644 files/fr/web/javascript/guide/index.html create mode 100644 files/fr/web/javascript/guide/introduction/index.html create mode 100644 files/fr/web/javascript/guide/iterateurs_et_generateurs/index.html create mode 100644 files/fr/web/javascript/guide/javascript_overview/index.html create mode 100644 "files/fr/web/javascript/guide/le_mod\303\250le_objet_javascript_en_d\303\251tails/index.html" create mode 100644 "files/fr/web/javascript/guide/le_protocole_it\303\251rateur_historique/index.html" create mode 100644 files/fr/web/javascript/guide/modules/index.html create mode 100644 "files/fr/web/javascript/guide/m\303\251taprogrammation/index.html" create mode 100644 files/fr/web/javascript/guide/nombres_et_dates/index.html create mode 100644 "files/fr/web/javascript/guide/objets_\303\251l\303\251mentaires_javascript/index.html" create mode 100644 "files/fr/web/javascript/guide/retours_sur_h\303\251ritage/index.html" create mode 100644 files/fr/web/javascript/guide/types_et_grammaire/index.html create mode 100644 files/fr/web/javascript/guide/utiliser_le_json_natif/index.html create mode 100644 files/fr/web/javascript/guide/utiliser_les_objets/index.html create mode 100644 files/fr/web/javascript/guide/utiliser_les_promesses/index.html create mode 100644 "files/fr/web/javascript/guide/\303\251galit\303\251_en_javascript/index.html" (limited to 'files/fr/web/javascript/guide') diff --git a/files/fr/web/javascript/guide/apropos/index.html b/files/fr/web/javascript/guide/apropos/index.html new file mode 100644 index 0000000000..89cc90c690 --- /dev/null +++ b/files/fr/web/javascript/guide/apropos/index.html @@ -0,0 +1,138 @@ +--- +title: A propos de ce guide +slug: Web/JavaScript/Guide/Apropos +tags: + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Introduction +--- +

{{jsSidebar("JavaScript Guide")}}

+ +

JavaScript est un langage de script orienté objet et indépendant de la plateforme. Ce guide explique tout ce que vous devriez savoir pour utiliser JavaScript.

+ +

Nouvelles fonctionalités selon les versions de JavaScript

+ +

+ +

Ce que vous devriez déjà connaître

+ +

Ce guide présuppose que vous possédez déjà les connaissances suivantes :

+ + + +

Versions de JavaScript

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tableau des versions de JavaScript et des navigateurs correspondants
Version JavaScriptVersion du navigateur
JavaScript 1.0Navigator 2.0
JavaScript 1.1Navigator 3.0
JavaScript 1.2Navigator 4.0-4.05
JavaScript 1.3Navigator 4.06-4.7x
JavaScript 1.4 
JavaScript 1.5Navigator 6.0
+ Mozilla (open source browser)
JavaScript 1.6Firefox 1.5 et les autres produits Mozilla basés sur Gecko 1.8
JavaScript 1.7Firefox 2 et les autres produits Mozilla basés sur Gecko 1.8
JavaScript 1.8Firefox 3 et les autres produits Mozilla basés sur Gecko 1.9
+ +

Où trouver de l'information sur JavaScript

+ +

La documentation JavaScript se trouve dans les ouvrages suivants:

+ + + +

Si vous découvrez JavaScript, commencez par le guide JavaScript. Une fois familiarisé avec les fondamentaux, vous pourrez utiliser la référence JavaScript pour plus de détails sur les objets et les instructions.

+ +

Astuces pour l'apprentissage du JavaScript

+ +

Commencer l'apprentissage de JavaScript est assez simple : tout ce dont vous avez besoin c'est d'un navigateur Web récent. Ce guide intègre quelques fonctions JavaScript qui ne sont disponibles qu'avec les dernières versions de Firefox (et/ou les autres navigateurs basés sur le moteur Gecko), aussi est-il recommandé d'utiliser la version la plus récente de Firefox.

+ +

Deux outils utiles sont nativement intégrés à Firefox et permettent de manipuler du JavaScript : la console web et l'ardoise JavaScript.

+ +

La console web

+ +

La console web permet d'afficher des informations sur la page web chargée dans le navigateur. Elle possède également une ligne de commande qui permet d'exécuter des expressions JavaScript dans la page courante.

+ +

Pour ouvrir la console web, aller dans le menu « Outils » puis « Développement web » puis « Console web ». La console apparaîtra en base de la fenêtre du navigateur. En bas de cette console se situe une ligne de commande qui peut être utilisée pour saisir du JavaScript :

+ +

+ +

L'ardoise JavaScript

+ +

La console web permet d'exécuter des lignes de JavaScript une à une. Dès qu'on souhaite exécuter plusieurs lignes, la console n'est plus très pratique. De plus, il est impossible d'enregistrer du code grâce à la console web. Pour mettre en place des exemples plus complexes, l'ardoise JavaScript sera plus adaptée.

+ +

Pour ouvrir l'ardoise, aller dans le menu « Outils » puis « Développement web » puis « Ardoise JavaScript ». Elle s'ouvre dans une fenêtre séparée et contient un éditeur qui permet d'écrire et d'exécuter du JavaScript dans le navigateur. Elle permet également de sauvegarder/charger des scripts sur votre ordinateur

+ +

Si vous utiliser l'option aller dans le menu « Examiner », le code contenu dans l'ardoise sera exécuter dans le navigateur et le résultat sera renvoyé dans l'éditeur sous forme d'un commentaire :

+ +

+ +

Conventions

+ +

Les applications JavaScript fonctionnent sur de nombreux systèmes d'exploitations. Les informations de ce guide doivent s'appliquer à l'ensemble des systèmes sur lesquels fonctionne JavaScript.

+ +

Ce guide utilise des URL de la forme suivante :

+ +

http://serveur.domaine/chemin/fichier.html

+ +

Dans ces URL, serveur représente le nom du serveur à partir duquel on lance l'application ; domaine représente le nom de domaine utilisé (par exemple netscape.com ou uiuc.edu) ; chemin représente l'arborescence du serveur et fichier.html représente un fichier dans cette arborescence. Généralement, les éléments représentés en italique dans l'URL seront des paramètres et les éléments représentés en police à chasse fixe seront à prendre au sens littéral. Si votre serveur permet d'utiliser SSL/TLS, vous pourrez utiliser https à la place de http.

+ +

Ce guide utilise les conventions de typographie suivantes :

+ + + +
+

« PrécédentSuivant »

+
+ +

 

diff --git "a/files/fr/web/javascript/guide/boucles_et_it\303\251ration/index.html" "b/files/fr/web/javascript/guide/boucles_et_it\303\251ration/index.html" new file mode 100644 index 0000000000..0646c94d53 --- /dev/null +++ "b/files/fr/web/javascript/guide/boucles_et_it\303\251ration/index.html" @@ -0,0 +1,349 @@ +--- +title: Boucles et itérations +slug: Web/JavaScript/Guide/Boucles_et_itération +tags: + - Guide + - JavaScript + - Syntax +translation_of: Web/JavaScript/Guide/Loops_and_iteration +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Contr%C3%B4le_du_flux_Gestion_des_erreurs", "Web/JavaScript/Guide/Fonctions")}}
+ +

Les boucles permettent de répéter des actions simplement et rapidement. Ce chapitre du guide JavaScript présente les différentes instructions qu'il est possible d'utiliser en JavaScript pour effectuer des itérations.

+ +

Les boucles permettent de répéter des actions simplement et rapidement. Une boucle peut être vue comme une version informatique de « copier N lignes » ou de « faire X fois quelque chose ». Par exemple, en JavaScript, on pourrait traduire « Faire 5 pas vers l'est » avec cette boucle :

+ +
for (let pas = 0; pas < 5; pas++) {
+  // Ceci sera exécuté 5 fois
+  // À chaque éxécution, la variable "pas" augmentera de 1
+  // Lorsque'elle sera arrivée à 5, le boucle se terminera.
+  console.log('Faire ' + pas + ' pas vers l\'est');
+}
+
+ +

Il y a différents types de boucles mais elles se ressemblent toutes au sens où elles répètent une action un certain nombre de fois (ce nombre peut éventuellement être zéro). Les différents types de boucles permettent d'utiliser différentes façon de commencer et de terminer une boucle. Chaque type de boucle pourra être utilisé en fonction de la situation et du problème que l'on cherche à résoudre.

+ +

Voici les différentes boucles fournies par JavaScript :

+ + + +

L'instruction for

+ +

Une boucle {{jsxref("statements/for", "for")}} répète des instructions jusqu'à ce qu'une condition donnée ne soit plus vérifiée. La boucle for JavaScript ressemble beaucoup à celle utilisée en C ou en Java. Une boucle for s'utilise de la façon suivante :

+ +
for ([expressionInitiale]; [condition]; [expressionIncrément])
+  instruction
+
+ +

Voici ce qui se passe quand une boucle for s'exécute :

+ +
    +
  1. L'expression initiale expressionInitiale est exécutée si elle est présente. Généralement, on utilise cette expression pour initialiser un ou plusieurs compteurs dont on se servira dans la boucle. Il est possible d'utiliser des expressions plus complexes si besoin. Elle peut servir à déclarer des variables.
  2. +
  3. L'expression condition est évaluée, si elle vaut true, les instructions contenues dans la boucle sont exécutées. Si la valeur de condition est false, la boucle for se termine. Si la condition est absente, elle est considérée comme true.
  4. +
  5. L'instruction instruction est exécutée. Si l'on souhaite exécuter plusieurs instructions, on utilisera un bloc d'instructions ({ ... }) afin de les grouper.
  6. +
  7. Si elle est présente, l'expression de mise à jour expressionIncrément est exécutée.
  8. +
  9. On retourne ensuite à l'étape 2.
  10. +
+ +

Exemple

+ +

La fonction suivante contient une instruction for qui compte le nombre d'options sélectionnées dans une liste déroulante (ici, un objet {{HTMLElement("select")}} permettant une sélection multiple). L'instruction for déclare une variable i et l'initialise à zéro. Elle vérifie que i est bien inférieur au nombre d'options et, pour chaque option, effectue un test conditionnel pour savoir si l'option est sélectionnée puis passe à l'option suivante en incrémentant la variable i pour chaque itération.

+ +
<form name="selectForm">
+  <p>
+    <label for="typesMusique">Veuillez choisir des genres musicaux, puis cliquez :</label>
+    <select id="typesMusique" name="typesMusique" multiple="multiple">
+      <option selected="selected">R&B</option>
+      <option>Jazz</option>
+      <option>Blues</option>
+      <option>New Age</option>
+      <option>Classique</option>
+      <option>Opera</option>
+    </select>
+  </p>
+  <p><button id="btn" type="button">Combien sont sélectionnés ?</button></p>
+</form>
+
+<script>
+function quantité(selectObject) {
+  let qtéSélectionnée = 0;
+  for (let i = 0; i < selectObject.options.length; i++) {
+    if (selectObject.options[i].selected) {
+      qtéSélectionnée++;
+    }
+  }
+  return qtéSélectionnée;
+}
+
+let btn = document.getElementById("btn");
+btn.addEventListener("click", function(){
+  alert('Nombre d\'options choisies : ' + quantité(document.selectForm.typesMusique))
+});
+</script>
+
+
+ +

L'instruction do...while

+ +

L'instruction {{jsxref("statements/do...while", "do...while")}} permet de répéter un ensemble d'instructions jusqu'à ce qu'une condition donnée ne soit plus vérifiée. (NdT : littéralement « do...while » signifie « faire... tant que »). Une instruction do...while s'utilise de la façon suivante :

+ +
do
+  instruction
+while (condition);
+
+ +

instruction est exécutée au moins une fois avant que la condition soit vérifiée. Pour utiliser plusieurs instructions à cet endroit, on utilisera une instruction de bloc ({ ... }) pour regrouper différentes instructions. Si la condition est vérifiée, l'instruction est à nouveau exécutée. À la fin de chaque exécution, la condition est vérifiée. Quand la condition n'est plus vérifiée (vaut false ou une valeur équivalente), l'exécution de l'instruction do...while est stoppée et le contrôle passe à l'instruction suivante.

+ +

Exemple

+ +

Dans l'exemple qui suit, la boucle do est exécutée au moins une fois et répétée jusqu'à ce que i ne soit plus inférieur à 5.

+ +
let i = 0;
+do {
+  i += 1;
+  console.log(i);
+} while (i < 5);
+ +

L'instruction while

+ +

Une instruction {{jsxref("statements/while", "while")}} permet d'exécuter une instruction tant qu'une condition donnée est vérifiée. Cette instruction while s'utilise de la façon suivante :

+ +
while (condition)
+  instruction
+
+ +

Si la condition n'est pas vérifiée, l'instruction instruction n'est pas exécutée et le contrôle passe directement à l'instruction suivant la boucle.

+ +

Le test de la condition s'effectue avant d'exécuter instruction. Si la condition renvoie true (ou une valeur équivalente), instruction sera exécutée et la condition sera testée à nouveau. Si la condition renvoie false (ou une valeur équivalente), l'exécution s'arrête et le contrôle est passé à l'instruction qui suit while.

+ +

Pour pouvoir utiliser plusieurs instructions dans la boucle, on utilisera une instruction de bloc ({ ... }) afin de les regrouper.

+ +

Exemple 1

+ +

La boucle while qui suit permet d'effectuer des itérations tant que n est inférieur à 3 :

+ +
let n = 0;
+let x = 0;
+while (n < 3) {
+  n++;
+  x += n;
+}
+
+ +

À chaque itération, la boucle incrémente n et ajoute la valeur de n à x. x et n prendront ainsi les valeurs suivantes :

+ + + +

Une fois la troisième itération effectuée, la condition n < 3 n'est plus vérifiée, par conséquent, la boucle se termine.

+ +

Exemple 2

+ +

Attention à éviter les boucles infinies. Il faut bien s'assurer que la condition utilisée dans la boucle ne soit plus vérifiée à un moment donné. Si la condition est toujours vérifiée, la boucle se répétera sans jamais s'arrêter. Dans l'exemple qui suit, les instructions contenues dans la boucle while s'exécutent sans discontinuer car la condition est toujours vérifiée :

+ +
while (true) {
+  console.log("Coucou monde !");
+}
+ +

L'instruction label

+ +

Un {{jsxref("statements/label","label")}} (ou étiquette) permet de fournir un identifiant pour une instruction afin d'y faire référence depuis un autre endroit dans le programme. On peut ainsi identifier une boucle grâce à un label puis utiliser les instructions break ou continue pour indiquer si le programme doit interrompre ou poursuivre l'exécution de cette boucle.

+ +

On utilise un label de la façon suivante :

+ +
label:
+  instruction
+
+ +

La valeur de label peut être n'importe quel identifiant JavaScript valide (et ne doit pas être un mot réservé pour le langage). L'instruction peut être n'importe quelle instruction JavaScript valide (y compris un bloc).

+ +

Exemple

+ +

Dans cet exemple, on utilise un label memoBoucle pour identifier une boucle while.

+ +
memoBoucle:
+while (memo == true) {
+  faireQQC();
+}
+ +
+

Note : Pour plus de détails sur cette instruction, voir la page de la référence JavaScript pour label.

+
+ +

L'instruction break

+ +

L'instruction {{jsxref("statements/break","break")}} est utilisée pour finir l'exécution d'une boucle, d'une instruction switch, ou avec un label.

+ + + +

La syntaxe de cette instruction possède donc deux formes :

+ +
    +
  1. break;
  2. +
  3. break label;
  4. +
+ +

La première forme permet d'interrompre la boucle la plus imbriquée (ou le switch) dans laquelle on se trouve. La seconde forme interrompt l'exécution d'une instruction identifiée par un label.

+ +

Exemple 1

+ +

Dans l'exemple qui suit, on itère sur un tableau grâce à une boucle jusqu'à trouver un élément dont la valeur est valeurTest :

+ +
for (i = 0; i < a.length; i++) {
+  if (a[i] === valeurTest) {
+    break;
+  }
+}
+ +

Exemple 2

+ +

Ici, on utilise break des deux façons : avec une instruction représentée par un label et sans.

+ +
let x = 0;
+let z = 0;
+labelAnnuleBoucle: while (true) {
+  console.log("Boucle externe : " + x);
+  x += 1;
+  z = 1;
+  while (true) {
+    console.log("Boucle interne : " + z);
+    z += 1;
+    if (z === 10 && x === 10) {
+      break labelAnnuleBoucle;
+    } else if (z === 10) {
+      break;
+    }
+  }
+}
+
+ +

L'instruction continue

+ +

L'instruction {{jsxref("statements/continue","continue")}} permet de reprendre une boucle while, do-while, for, ou une instruction label.

+ + + +

L'instruction continue s'utilise donc de la façon suivante :

+ +
    +
  1. continue;
  2. +
  3. continue label;
  4. +
+ +

Exemple 1

+ +

Dans l'exemple qui suit, on utilise une boucle while avec une instruction continue qui est exécutée lorsque i vaut 3. Ici, n prendra donc les valeurs 1, 3, 7 et 12.

+ +
let i = 0;
+let n = 0;
+while (i < 5) {
+  i++;
+  if (i === 3) {
+    continue;
+  }
+  n += i;
+  console.log(n);
+}
+// 1, 3, 7, 12
+
+
+ +

Exemple 2

+ +

Dans l'exemple suivant, on a une instruction étiquetée vérifIetJ qui contient une autre instruction étiquetée vérifJ. Si l'instruction continue est utilisée, le programme reprend l'exécution au début de l'instruction vérifJ. Chaque fois que continue est utilisé, vérifJ réitère jusqu'à ce que sa condition renvoie false. Lorsque c'est le cas, le reste de l'instruction vérifIetJ est exécuté.

+ +

Si continue utilisait l'étiquette vérifIetJ, le programme continuerait au début de l'instruction vérifIetJ

+ +
let i = 0;
+let j = 8;
+
+vérifIetJ: while (i < 4) {
+  console.log("i : " + i);
+  i += 1;
+
+  vérifJ: while (j > 4) {
+    console.log("j : "+ j);
+    j -= 1;
+    if ((j % 2) === 0){
+      continue vérifJ;
+    }
+    console.log(j + " est impaire.");
+   }
+   console.log("i = " + i);
+   console.log("j = " + j);
+}
+ +

L'instruction for...in

+ +

L'instruction {{jsxref("statements/for...in","for...in")}} permet d'itérer sur l'ensemble des propriétés énumérables d'un objet. Pour chaque propriété, JavaScript exécutera l'instruction indiquée. Cette instruction s'utilise de la façon suivante :

+ +
for (variable in objet) {
+  instruction
+}
+
+ +

Exemple

+ +

La fonction suivante prend comme argument un objet et le nom de cet objet. Elle parcourt ensuite les propriétés de l'objet et renvoie une chaîne de caractères qui liste les propriétés avec leurs noms et leurs valeurs respectives :

+ +
function afficherProps(obj, nomObj) {
+  var result = "";
+  for (var i in obj) {
+    result += nomObj + "." + i + " = " + obj[i] + "\n";
+  }
+  result += "\n";
+  return result;
+}
+
+ +

Pour un objet voiture dont les propriétés sont fabricant et modèle, result serait :

+ +
voiture.fabricant = Ford
+voiture.modèle = Mustang
+
+ +

Les tableaux (arrays) et for...in

+ +

Bien qu'il soit tentant d'utiliser cette instruction pour parcourir les éléments d'un objet Array , cela peut avoir des comportements inattendus. En effet, for...in permet de parcourir les propriétés définies par l'utilisateur ainsi que les éléments de tableau. Ainsi, si l'on modifie un objet Array en lui ajoutant des propriétés et/ou des méthodes, la boucle for...in renverra le nom de ces nouvelles propriétés en plus des indices des éléments du tableau. C'est pourquoi, il est préférable d'utiliser une boucle for avec les indices du tableau pour parcourir ses éléments.

+ +

L'instruction for...of

+ +

L'instruction {{jsxref("statements/for...of","for...of")}} crée une boucle qui fonctionne avec les objets itérables (qui incluent {{jsxref("Array")}}, {{jsxref("Map")}}, {{jsxref("Set")}}, l'objet arguments, etc.). La boucle appelle un mécanisme d'itération propre à l'objet utilisé et elle parcourt l'objet et les valeurs de ses différentes propriétés.

+ +
for (variable of objet) {
+  instruction
+}
+ +

Dans l'exemple suivant, on illustre la différence entre une boucle for...of et une boucle for...infor...in parcourt les noms des propriétés d'un objet alors que for...of parcourt les valeurs des propriétés :

+ +
let arr = [3, 5, 7];
+arr.toto = "coucou";
+
+for (let i in arr) {
+  console.log(i); // affiche 0, 1, 2, "toto" dans la console
+}
+
+for (let i of arr) {
+  console.log(i); // affiche 3, 5, 7 dans la console
+}
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Contr%C3%B4le_du_flux_Gestion_des_erreurs", "Web/JavaScript/Guide/Fonctions")}}

diff --git "a/files/fr/web/javascript/guide/collections_avec_cl\303\251s/index.html" "b/files/fr/web/javascript/guide/collections_avec_cl\303\251s/index.html" new file mode 100644 index 0000000000..82a275c036 --- /dev/null +++ "b/files/fr/web/javascript/guide/collections_avec_cl\303\251s/index.html" @@ -0,0 +1,152 @@ +--- +title: Collections avec clés +slug: Web/JavaScript/Guide/Collections_avec_clés +tags: + - Collections + - Guide + - JavaScript + - Map + - set +translation_of: Web/JavaScript/Guide/Keyed_collections +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Collections_indexées", "Web/JavaScript/Guide/Utiliser_les_objets")}}
+ +

Ce chapitre présente les collections de données qui sont ordonnées avec une clé. Les objets Map et Set contiennent des éléments sur lesquels on peut itérer dans leur ordre d'insertion.

+ +

Maps

+ +

Le type Map

+ +

ECMAScript 2015 introduit une nouvelle structure de données pour faire correspondre des données entre elle. Un objet {{jsxref("Map")}} représente une collection de données qui sont des correspondances entre des clés ou valeurs et pour lequel on peut itérer dans l'ordre d'insertion pour lister les différentes clés / valeurs.

+ +

Le code suivant illustre certaines opérations basiques avec Map. Pour plus d'informations sur cet objet, voir également la page de référence {{jsxref("Map")}}. Il est possible d'utiliser une boucle {{jsxref("Instructions/for...of","for...of")}} pour renvoyer un tableau [clé, valeur] à chaque itération.

+ +
var sayings = new Map();
+sayings.set("dog", "woof");
+sayings.set("cat", "meow");
+sayings.set("elephant", "toot");
+sayings.size; // 3
+sayings.get("fox"); // undefined
+sayings.has("bird"); // false
+sayings.delete("dog");
+
+for (var [key, value] of sayings) {
+  console.log(key + " goes " + value);
+}
+// "cat goes meow"
+// "elephant goes toot"
+
+ +

Comparaison entre les types Object et Map

+ +

Habituellement, les objets {{jsxref("Object", "objets", "", 1)}} ont été utilisés pour faire correspondre des chaînes avec des valeurs. Les objets permettent d'associer des clés avec des valeurs, de récupérer ces valeurs, de supprimer des clés, de détecter si quelque chose est enregistré dans une clé. Le type Map possède cependant certains avantages pour être utilisés comme maps.

+ + + +

Pour savoir si on doit utiliser le type Map ou le type Object, on peut considérer les aspects suivants :

+ + + +

Le type WeakMap

+ +

L'objet {{jsxref("WeakMap")}} est une collection de paires clés/valeurs pour lesquelles les clés sont uniquement des objets (les valeurs peuvent être d'un type arbitraire). Les références vers les objets sont des références « faibles ». Cela signifie qu'elles seront collectées par le ramasse-miettes s'il n'y a pas d'autres références vers cet objet. L'API WeakMap offre les mêmes fonctionnalités que l'API Map.

+ +

La différence entre le type Map et le type WeakMap est que les clés d'un objet WeakMap ne sont pas énumérables (c'est-à-dire qu'on n'a pas de méthode pour donner la liste des clés). S'il en existait une, la liste dépendrait de l'état d'avancement du ramasse-miettes, ce qui introduirait un non-déterminisme.

+ +

Pour plus d'informations et d'exemples, voir également le paragraphe « Pourquoi WeakMap ? » sur l'article {{jsxref("WeakMap")}} de la référence.

+ +

Un cas d'utilisation des objets WeakMap est le stockage de données privées d'un objet ou pour cacher certains détails d'implémentation. L'exemple qui suit est tiré du billet de blog de Nick Fitzgerald « Masquer des détails d'implémentation avec les WeakMaps ECMAScript 6 ». Les données et méthodes privées sont stockées dans l'objet WeakMap privates. Tout ce qui est exposé par l'instance et le prototype est public. Tout ce qui est en dehors est inaccessible car privates n'est pas exporté depuis le module :

+ +
const privates = new WeakMap();
+
+function Public() {
+  const me = {
+    // Les données privées ici
+  };
+  privates.set(this, me);
+}
+
+Public.prototype.method = function () {
+  const me = privates.get(this);
+  // On fait des choses avec les données privées dans `me`...
+};
+
+module.exports = Public;
+
+ +

Les ensembles

+ +

Le type Set

+ +

Les objets {{jsxref("Set")}} sont des ensembles de valeurs. Il est possible de les parcourir dans l'ordre d'insertion des éléments. Une valeur d'un élément Set ne peut y apparaître qu'une seule fois, il est unique pour cette instance de Set.

+ +

Le code suivant illustre certaines opérations basiques avec Set. Voir aussi la page {{jsxref("Set")}} pour plus d'exemples et l'API complète.

+ +
var monEnsemble = new Set();
+monEnsemble.add(1);
+monEnsemble.add("du texte");
+monEnsemble.add("toto");
+
+monEnsemble.has(1); // true
+monEnsemble.delete("toto");
+monEnsemble.size; // 2
+
+for (let item of monEnsemble) console.log(item);
+// 1
+// "du texte"
+
+ +

Convertir des tableaux (Array) en ensembles (Set)

+ +

Il est possible de créer un {{jsxref("Array")}} à partir d'un Set grâce à {{jsxref("Array.from")}} ou l'opérateur de décomposition. Pour effectuer la conversion dans l'autre sens, on peut utiliser le constructeur Set avec un argument de type Array. Encore une fois, les objets Set stockent des valeurs uniques, les éléments dupliqués dans un tableau seront supprimés lors de la conversion.

+ +
Array.from(monSet);
+[...monSet2];
+
+monSet2 = new Set([1,2,3,4]);
+
+ +

Comparaison entre Array et Set

+ +

Historiquement, on représentait des ensembles avec des tableaux JavaScript. Ce nouveau type, Set, possède certains avantages :

+ + + +

Le type WeakSet

+ +

Les objets {{jsxref("WeakSet")}} sont des ensembles d'objets. Un objet d'un WeakSet ne peut y apparaître qu'une seule fois maximum. On ne peut pas itérer sur les objets WeakSet (ils ne sont pas énumérables).

+ +

Les principales différences avec l'objet {{jsxref("Set")}} sont :

+ + + +

Les cas d'utilisations pour les objets WeakSet objects sont relativement limités. Ils empêcheront toute fuite mémoire donc on pourra, de façon sécurisée, les utiliser avec des éléments DOM qui pourront être des clés (pour les utiliser par ailleurs, etc.).

+ +

Égalité des clés et des valeurs avec Map et Set

+ +

L'égalité utilisée pour les clés des objets Map et celle utilisée pour les valeurs des objets Set sont les mêmes : elles sont basées sur l'algorithme suivant :

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Collections_indexées", "Web/JavaScript/Guide/Utiliser_les_objets")}}

diff --git "a/files/fr/web/javascript/guide/collections_index\303\251es/index.html" "b/files/fr/web/javascript/guide/collections_index\303\251es/index.html" new file mode 100644 index 0000000000..7efda85419 --- /dev/null +++ "b/files/fr/web/javascript/guide/collections_index\303\251es/index.html" @@ -0,0 +1,425 @@ +--- +title: Collections indexées +slug: Web/JavaScript/Guide/Collections_indexées +tags: + - Array + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Indexed_collections +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_régulières", "Web/JavaScript/Guide/Collections_avec_clés")}}
+ +

Ce chapitre présente les collections de données qui sont ordonnées par un indice. Cela inclue les tableaux et les objets semblables à des tableaux que sont les objets {{jsxref("Array")}} et les objets {{jsxref("TypedArray")}}.

+ +

Le type Array

+ +

Un tableau (array en anglais) est un ensemble ordonné de valeurs auxquelles on peut faire référence avec un nom et un indice. Par exemple, si on a un tableau emp qui contient les noms d'employés indexés par leurs numéros d'employé, on pourrait utiliser emp[1] pour accéder à l'employé n°1, emp[2] pour accéder au deuxième et ainsi de suite.

+ +

JavaScript ne possède pas de type particulier pour représenter un tableau de données. En revanche, il est possible d'utiliser l'objet natif Array ainsi que ses méthodes pour manipuler des tableaux. L'objet Array possède plusieurs méthodes qui permettent de manipuler les tableaux pour les fusionner, les inverser, les trier, etc. Il possède une propriété de longueur ainsi que d'autres propriétés qui peuvent être utilisées avec les expressions rationnelles.

+ +

Créer un tableau

+ +

Les instructions qui suivent sont équivalentes et permettent de créer le même tableau :

+ +
var arr = new Array(élément0, élément1, ..., élémentN);
+var arr = Array(élément0, élément1, ..., élémentN);
+var arr = [élément0, élément1, ..., élémentN];
+
+ +

élément0, élément1, ..., élémentN est une liste de valeurs qui formeront les éléments du tableau. Lorsque ces valeurs sont définies, le tableau initialisera la valeur des éléments correspondants. La propriété length du tableau permet de connaître le nombre d'arguments du tableau.

+ +

Parmi les instructions précédentes, une utilise des crochets, on appelle ceci un « littéral de tableau » ou un « initialisateur de tableau ». Cette notation est plus courte que les autres et est souvent préférée pour sa lisibilité. Pour plus d'informations sur cette notation, voir la page sur les littéraux de tableaux pour plus détails.

+ +

Afin de créer un tableau de longueur non nulle mais sans aucun élément initialisé, on peut utiliser l'une des deux instructions suivantes :

+ +
var arr = new Array(longueurTableau);
+var arr = Array(longueurTableau);
+
+// Cela aura le même effet que :
+var arr = [];
+arr.length = longueurTableau;
+
+ +
+

Note : Dans le code ci-dessus longueurTableau doit être un nombre. Si ce n'est pas le cas, un tableau d'un seul élément (ayant la valeur fournie) sera créé. arr.length renverra longueurTableau, mais le tableau ne contiendra que des éléments « vides » non définis. Si on utilise une boucle {{jsxref("Instructions/for...in")}} sur ce tableau, on ne trouvera aucun élément.

+
+ +

On a vu comment créer un tableau, il est aussi possible d'affecter des tableaux à des propriétés d'objets (que ce soit lors de leur création ou pour les modifier) :

+ +
var obj = {};
+// ...
+obj.prop = [élément0, élément1, ..., élémentN];
+
+// OU
+var obj = {prop: [élément0, élément1, ...., élémentN]}
+
+ +

Si on souhaite initialiser un tableau avec un seul élément et que cet élément est un nombre, il est nécessaire d'utiliser la notation littérale. En effet, si un nombre est passé à la fonction Array() pour construire le tableau, celui-ci sera interprété comme une longueur et non comme la valeur d'un élément.

+ +
var arr1 = [42];      // Le tableau créé contient bien un élément qui vaut 42
+var arr2 = Array(42); // Crée un tableau sans élément
+                      // mais dont arr.length vaut 42
+
+// Le code ci-dessus est équivalent à
+var arr = [];
+arr.length = 42 ;
+
+ +

Si N est un nombre décimal dont la partie fractionnaire n'est pas nulle, tout appel à Array(N) renverra une exception RangeError. Par exemple :

+ +
var arr = Array(9.3);  // RangeError: Invalid array length
+
+ +

Si on souhaite créer un tableau d'un seul élément et ce quel que soit le type de données, il sera préférable d'utiliser les littéraux de tableaux. Sinon, on peut créer un tableau vide puis lui ajouter un seul élément.

+ +

Avec ES2015 (anciennement ECMAScript 6), on peut utiliser la méthode {{jsxref("Array.of")}} afin de créer un tableau composé d'un seul élément :

+ +
let monTableau = Array.of("Joconde"); // monTableau contient uniquement "Joconde"
+ +

Remplir un tableau

+ +

Il est possible de remplir un tableau en affectant des valeurs à ses éléments. Par exemple :

+ +
var emp = [];
+emp[0] = "Casey Jones";
+emp[1] = "Phil Lesh";
+emp[2] = "August West";
+
+ +
+

Note : Si on utilise une valeur non entière pour désigner un élément du tableau, cela créera une propriété sur l'objet plutôt qu'un élément du tableau :

+ +
var arr = [];
+arr[3.4] = "Oranges";
+console.log(arr.length);                // 0
+console.log(arr.hasOwnProperty(3.4));   // true
+
+
+ +

Il est aussi possible de remplir un tableau directement lors de sa création :

+ +
var monTableau = new Array("Coucou", maVar, 3.14159);
+var monTableau = ["Mangue", "Pomme", "Orange"]
+
+ +

Faire référence aux éléments d'un tableau

+ +

Il est possible de faire référence aux éléments d'un tableau en utilisant un nombre ordinal lié à l'élément. Ainsi, si on définit le tableau suivant :

+ +
var monTableau = ["Air", "Eau", "Feu"];
+
+ +

On pourra accéder au premier élément du tableau en utilisant monTableau[0], on accèdera au deuxième élément avec monTableau[1]. Les indices des éléments sont comptés à partir de 0.

+ +
+

Note : Les crochets peuvent également être utilisés pour faire référence aux propriétés du tableau (les tableaux sont des objets JavaScript à part entière). On pourra donc avoir :

+ +
var arr = ["un", "deux", "trois"];
+arr[2];         // "trois" - on accède à un élément du tableau
+arr["length"];  // 3 - on accède à une propriété du tableau
+
+
+ +

Comprendre la propriété length

+ +

En termes d'implémentation, les tableaux JavaScript stockent leurs éléments comme des propriétés normales, l'indice étant utilisé comme nom pour désigner la valeur de la propriété. La propriété length est elle un peu spéciale : elle renvoie toujours la valeur du plus grand indice du tableau plus 1. Dans l'exemple suivant, "Biduche" est placé à l'indice 30, chats.length renvoie donc 30 + 1). On rappelle que les indices des tableaux JavaScript commencent à partir de 0 et pas à partir de 1. Cela signifie que la valeur de la propriété length sera plus grande, de 1, par rapport à l'indice le plus élevé :

+ +
var chats = [];
+chats[30] = ['Biduche'];
+console.log(chats.length); // 31
+
+ +

Il est aussi possible d'affecter une valeur à la propriété length. Si la valeur fournie est inférieure au nombre d'éléments stockés, cela tronquera la tableau. Si la valeur est 0, cela videra le tableau :

+ +
var chats = ['Marie', 'Toulouse', 'Berlioz'];
+console.log(chats.length); // 3
+
+chats.length = 2;
+console.log(chats); // affiche "Marie,Toulouse" - Berlioz a été retiré
+
+chats.length = 0;
+console.log(chats); // affiche [], le tableau est vide
+
+chats.length = 3;
+console.log(chats); // [ <3 empty slots> ]
+
+ +

Parcourir un tableau

+ +

Un tableau est une structure de données qui se prête particulièrement aux boucles, on pourra utiliser ces dernières pour parcourir les éléments du tableau de façon itérative. Voici un exemple de parcours simple :

+ +
var couleurs = ['rouge', 'vert', 'bleu'];
+for (var i = 0; i < couleurs.length; i++) {
+  console.log(couleurs[i]);
+}
+
+ +

Si on sait qu'aucun des éléments ne vaut false dans un contexte booléen (par exemple, si le tableau contient des nœuds du DOM), on peut utiliser une formulation encore plus concise :

+ +
var divs = document.getElementsByTagName('div');
+for (var i = 0, div; div = divs[i]; i++) {
+  /* On effectue un traitement sur les  div */
+}
+
+ +

Cette syntaxe permet d'éviter d'avoir à vérifier la longueur du tableau et de gérer l'affectation de la variable div pour chaque élément du tableau.

+ +

La méthode {{jsxref("Array.forEach", "forEach()")}} fournit une autre méthode pour parcourir un tableau :

+ +
var couleurs = ['rouge', 'vert', 'bleu'];
+couleurs.forEach(function(couleur) {
+  console.log(couleur);
+});
+
+ +

Avec les fonctions fléchées (apparues avec ES6 / ECMAScript 2015), on peut obtenir un code plus concis :

+ +
var couleurs = ['rouge', 'vert', 'bleu'];
+couleurs.forEach(couleur => console.log(couleur));
+ +

La fonction passée comme argument à forEach() est exécutée une fois pour chacun des éléments du tableau (l'élément du tableau sera passé comme argument de cette fonction). Les éléments qui n'ont pas de valeur affectée ne sont pas parcourus lors d'une boucle forEach.

+ +

On notera que les éléments ne sont pas parcourus lorsqu'ils n'ont pas eu de valeur d'affectée. Cependant, si on a affecté la valeur {{jsxref("undefined")}} de façon explicite à un élément, il sera pris en compte lors de la boucle :

+ +
var tableau = ['premier', 'deuxième', , 'quatrième'];
+
+// affiche ['premier', 'deuxième', 'quatrième'];
+tableau.forEach(function(élément) {
+  console.log(élément);
+});
+
+if(tableau[2] === undefined) { console.log('tableau[2] vaut undefined'); } // true
+
+var tableau = ['premier', 'deuxième', undefined, 'quatrième'];
+
+// renvoie ['premier', 'deuxième', undefined, 'quatrième'];
+tableau.forEach(function(élément) {
+  console.log(élément);
+})
+ +

Étant donné que les éléments des tableaux sont stockés comme des propriétés classiques, il n'est pas conseillé d'utiliser des boucles {{jsxref("Instructions/for...in")}} pour parcourir les tableaux car cela listerait également les propriétés énumérables (en plus des éléments).

+ +

Méthodes des tableaux

+ +

L'objet Array possède les méthodes suivantes :

+ + + +

Du code permettant d'émuler ces fonctions est disponible sur chacune des pages (polyfill). Le support natif de ces fonctionnalités dans les différents navigateurs peut être trouvé ici.

+ + + +

Les méthodes présentées ci-avant qui prennent une fonction de rappel (callback) en argument sont appelées méthodes itératives car elles parcourent le tableau de façon itérative. Chacune de ces méthodes peut prendre en compte un deuxième argument (optionnel) qui sera l'objet this pris en compte par le callback. Si ce deuxième argument n'est pas fourni, this vaudra la valeur de l'objet global.

+ +

La fonction de rappel est appelée avec trois arguments : le premier étant la valeur de l'élément courant, le deuxième est l'indice de cet élément et le troisième représente le tableau lui-même. Les fonctions JavaScript ignorent les arguments supplémentaires qui ne sont pas déclarés explicitement dans la liste des paramètres, on peut donc utiliser une fonction prenant un seul argument comme fonction de rappel.

+ + + +

reduce() et reduceRight() sont à utiliser lorsqu'on souhaite n'obtenir qu'une seule valeur, récursivement, à partir des différents éléments du tableau. Pour plus d'informations sur l'utilisation d'une valeur d'initialisation pour ces deux fonctions, se référer à leurs pages : {{jsxref("Array.reduceRight")}} et {{jsxref("Array.reduce")}}

+ +

Tableaux multi-dimensionnels

+ +

Les tableaux peuvent être imbriqués les uns dans les autres. Cela signifie qu'un tableau peut avoir un élément dont la valeur est un tableau. En utilisant ce comportement, on peut donc créer des matrices, voire des tableaux à plusieurs dimensions.

+ +

Par exemple, avec le code suivant :

+ +
var a = new Array(4);
+for (i = 0; i < 4; i++) {
+  a[i] = new Array(4);
+  for (j = 0; j < 4; j++) {
+    a[i][j] = "[" + i + "," + j + "]";
+  }
+}
+
+ +

On pourra avoir le tableau suivant sur deux dimensions :

+ +
Ligne 0 : [0,0] [0,1] [0,2] [0,3]
+Ligne 1 : [1,0] [1,1] [1,2] [1,3]
+Ligne 2 : [2,0] [2,1] [2,2] [2,3]
+Ligne 3 : [3,0] [3,1] [3,2] [3,3]
+
+ +

Les tableaux et les expressions rationnelles

+ +

Lorsqu'un tableau est le résultat d'une correspondance entre une expression rationnelle et une chaîne de caractères, les éléments et propriétés du tableau fournissent des informations sur la correspondance. Les méthodes suivantes peuvent renvoyer un tableau : {{jsxref("Objets_globaux/RegExp/exec","RegExp.exec()")}}, {{jsxref("Objets_globaux/String/match/exec","String.match()")}},  {{jsxref("Objets_globaux/String/split","String.split()")}}. Pour plus d'informations sur les tableaux et les expressions rationnelles, voir le chapitre du guide JavaScript sur les expressions rationnelles.

+ +

Manipuler des objets semblables à des tableaux

+ +

Certains objets JavaScript tels que {{domxref("NodeList")}} (renvoyé par {{domxref("document.getElementsByTagName()")}}) ou l'objet arguments (disponible au sein d'une fonction) ressemblent à des tableaux mais n'en sont pas (ils n'ont pas toutes les méthodes décrites ci-avant par exemple). Ainsi, l'objet arguments fournit une propriété {{jsxref("Objets_globaux/Function/length","length")}} mais n'implémente pas la méthode {{jsxref("Array.forEach", "forEach()")}}.

+ +

Les méthodes du prototype des tableaux permettent d'utiliser les méthodes d'objets Array sur des objets semblables à des tableaux :

+ +
 function alertArguments() {
+   Array.prototype.forEach.call(arguments, function(item) {
+     console.log(item);
+   });
+ }
+
+ +

Il est possible d'utiliser ces méthodes génériques sur des chaînes de caractères :

+ +
Array.prototype.forEach.call("une chaîne", function(chr) {
+   console.log(chr);
+});
+ +

Les tableaux typés

+ +

Les tableaux typés JavaScript sont des objets semblables à des tableaux qui fournissent un moyen d'accéder à des données binaires. Comme on l'a vu ci-avant, les objets {{jsxref("Array")}} grandissent et rétrécissent dynamiquement et peuvent contenir n'importe quelle valeur JavaScript. Les moteurs JavaScript effectuent des optimisations afin que les tableaux puissent être utilisés rapidement. Cependant, avec le développement des applications web, les applications viennent à manipuler des données audio, vidéo, binaires et accèdent à des données brutes via les WebSockets d'autres outils. Il apparaît donc nécessaire d'avoir les outils JavaScript pertinents pour manipuler efficacement des données binaires, organisées au sein de tableaux typés.

+ +

Les vues et les tampons de mémoire (buffers) : l'architecture des tableaux typés

+ +

Afin de permettre un maximum de flexibilité et d'efficacité, les tableaux typés JavaScript séparent l'implémentation entre les tampons (buffers) et les vues (views). Un tampon de mémoire, implémenté par l'objet {{jsxref("ArrayBuffer")}}, est un objet représentant un fragment de données. Un tampon n'a pas de format a proprement parler et il ne fournit aucun mécanisme pour accéder à son contenu. Afin d'accéder à la mémoire contenu dans le tampon, on a besoin d'utiliser une vue. Une vue fournit un contexte, c'est-à-dire un type de donnée, un indice de départ et un nombre d'éléments, qui permet de traiter les données initiales comme un vrai tableau typé.

+ +

Typed arrays in an ArrayBuffer

+ +

ArrayBuffer

+ +

Le type {{jsxref("ArrayBuffer")}} est un type de donnée utilisé pour représenter un tampon de données binaire générique dont la longueur est fixée. Un tampon de données ne peut pas être manipulé directement. Pour manipuler les données, il faut créer une vue sur le tableau typé ou un objet {{jsxref("DataView")}} qui représente le tampon dans un format spécifique et qui pourra être utilisé pour lire et écrire des informations du tampon.

+ +

Les vues qui sont des tableaux typés

+ +

Les vues de tableaux typés possèdent des noms explicites et fournissent des vues pour les types numériques usuels tels que Int8, Uint32, Float64 et ainsi de suite. Il existe un type de vue spécial qui est Uint8ClampedArray. Ce type ramène les différentes valeurs exploitées entre 0 et 255. Cela peut notamment être utile pour le traitement des données d'un canvas.

+ +

{{page("/fr/docs/Web/JavaScript/Reference/Objets_globaux/TypedArray", "Les_objets_TypedArray")}}

+ +

Pour plus d'informations sur les tableaux typés, voir l'article de la référence sur les différents objets {{jsxref("TypedArray")}}.

+ +

{{PreviousNext("Web/JavaScript/Guide/Expressions_régulières", "Web/JavaScript/Guide/Collections_avec_clés")}}

diff --git "a/files/fr/web/javascript/guide/contr\303\264le_du_flux_gestion_des_erreurs/index.html" "b/files/fr/web/javascript/guide/contr\303\264le_du_flux_gestion_des_erreurs/index.html" new file mode 100644 index 0000000000..a267ed8c97 --- /dev/null +++ "b/files/fr/web/javascript/guide/contr\303\264le_du_flux_gestion_des_erreurs/index.html" @@ -0,0 +1,408 @@ +--- +title: Contrôle du flux d'instructions et gestion des erreurs +slug: Web/JavaScript/Guide/Contrôle_du_flux_Gestion_des_erreurs +tags: + - Débutant + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Types_et_grammaire", "Web/JavaScript/Guide/Boucles_et_itération")}}

+ +

JavaScript supporte nativement un ensemble d'instructions. Ces instructions permettent de définir les logiques des algorithmes, le flux des informations, etc. Ce chapitre fournit un aperçu sur le fonctionnement de ces différentes instructions JavaScript.

+ +

Toute expression est une instruction, voir la page Expressions et opérateurs pour plus d'informations sur les expressions. En JavaScript, le point-virgule (;) est utilisé afin de séparer des instructions dans le code.

+ +

Voir la Référence JavaScript pour plus de détails sur les différentes instructions décrites dans ce chapitre.

+ +

Les blocs

+ +

L'instruction la plus simple est l'instruction de bloc qui permet de regrouper des instructions. Un bloc est délimité par une paire d'accolades :

+ +
{
+   instruction_1;
+   instruction_2;
+   .
+   .
+   .
+   instruction_n;
+}
+
+ +

Exemple

+ +

Les instructions de blocs sont souvent utilisées avec les instructions conditionnelles et itératives telles que if, for, while.

+ +
while (x < 10) {
+  x++;
+}
+
+ +

Ici, { x++; } représente le bloc.

+ +

Note importante : En JavaScript, avant ECMAScript 2015 (aussi appelé ES6), les blocs n'introduisaient pas de nouvelles portées. Les variables introduites dans le bloc avec l'instruction var font partie de la portée de la fonction englobante ou du script. Les effets de leur définition persistent en dehors du bloc. Les blocs seuls utilisés avec var (et non let) pourront laisser penser que ce bloc se comportera comme en C ou en Java. Par exemple :

+ +
var x = 1;
+{
+  var x = 2;
+}
+console.log(x); // affichera 2
+
+ +

Cella affichera 2 car l'instruction var x contenue dans le bloc fait partie de la même portée que l'instruction var x écrite avant le bloc. En C ou en Java, le code équivalent à cet exemple aurait produit 1.

+ +

Cela a évolué avec ECMAScript 2015 (ES6). Les instructions letet const permettent de déclarer des variables dont la portée est celle du bloc courant. Voir les pages des références {{jsxref("Instructions/let","let")}} et {{jsxref("Instructions/const","const")}}.

+ +
+

Note : Pour plus d'informations sur les blocs, voir l'article sur les blocs de la référence JavaScript.

+
+ +

Les instructions conditionnelles

+ +

Une instruction conditionnelle est un ensemble de commandes qui s'exécutent si une condition donnée est vérifiée. JavaScript possède deux instructions conditionnelles : if...else et switch.

+ +

Instruction if...else

+ +

On utilise l'instruction if lorsqu'on souhaite exécuter une instruction si une condition logique est vérifiée (vraie). La clause else est optionnelle et permet de préciser les instructions à exécuter si la condition logique n'est pas vérifiée (l'assertion est fausse). Voici un exemple qui illustre l'utilisation de l'instruction if :

+ +
if (condition) {
+  instruction_1;
+} else {
+  instruction_2;
+}
+ +

condition peut correspondre à n'importe quelle expression qui est évaluée à true (vrai) ou false (faux). Voir la page sur les booléens pour plus d'informations sur les évaluations qui fournissent les valeurs true ou false. Si la condition vaut true, instruction_1 est exécutée, sinon instruction_2 sera exécutée. instruction_1 et instruction_2 peuvent correspondre à n'importe quelle instruction, y compris d'autres instructions if.

+ +

Si on doit tester différentes conditions les unes à la suite des autres, il est possible d'utiliser else if pour lier les différents tests. On l'utilise de la façon suivante :

+ +
if (condition_1) {
+  instruction_1;
+} else if (condition_2) {
+  instruction_2;
+} else if (condition_n) {
+  instruction_n;
+} else {
+  dernière_instruction;
+}
+ +

Afin d'exécuter plusieurs instructions, on peut les regrouper grâce aux blocs ({ ... }) vus précédemment. C'est une bonne pratique que de les utiliser, surtout si on imbrique plusieurs instructions if les unes dans les autres:

+ +
if (condition) {
+  instruction_1_exécutée_si_condition_vraie;
+  instruction_2_exécutée_si_condition_vraie;
+} else {
+  instruction_3_exécutée_si_condition_fausse;
+  instruction_4_exécutée_si_condition_fausse;
+}
+
+ +
Attention à ne pas utiliser des intructions d'affectation dans les expressions conditionnelles. On peut, en effet, très facilement confondre l'affectation et le test d'égalité en lisant le code. Voici un exemple de ce qu'il ne faut pas faire :
+ +
if (x = y) {
+  /* exécuter des instructions */
+}
+
+ +

Ici, on ne teste pas si x vaut y, on affecte la valeur de y à x ! Si vous devez à tout prix utiliser une affectation dans une expression conditionnelle, une bonne pratique sera d'ajouter des parenthèses en plus autour de l'affectation. Par exemple :

+ +
if ((x = y)) {
+  /* exécuter des instructions */
+}
+
+ +

Valeurs équivalents à false dans un contexte booléen (falsy values)

+ +

Lors d'un test, les valeurs suivantes seront considérées comme équivalentes à false :

+ + + +

Les autres valeurs, y compris les objets, seront équivalents à true.

+ +

Attention à ne pas confondre les valeurs booléennes « primitives » true et false avec les valeurs crées grâce à un objet Boolean. Par exemple, on aura :

+ +
var b = new Boolean(false);
+if (b) // cette condition est bien vérifiée !
+if (b === true) // cette condition n'est pas vérifiée !
+
+
+ +

Exemple

+ +

Dans l'exemple qui suit, la fonction checkData renvoie true si une chaîne de caractères mesure trois caractères. Sinon, elle affiche une alerte et renvoie false.

+ +
function checkData(maChaîne) {
+  if (maChaîne.length == 3) {
+    return true;
+  } else {
+    alert("Veuillez saisir trois caractères. " +
+      maChaîne + " n'est pas valide.");
+    return false;
+  }
+}
+
+ +
+

Note : Pour plus d'informations sur cette instruction, voir la page de la référence JavaScript sur if, else et else if.

+
+ +

L'instruction switch

+ +

L'instruction switch permet à un programme d'évaluer une expression et d'effectuer des instructions en fonction des différents cas de figures correspondants aux différentes valeurs. Si un cas correspond au résultat de l'évaluation, le programme exécute l'instruction associée. Voici un exemple utilisant une instruction switch :

+ +
switch (expression) {
+  case label_1:
+    instructions_1
+    [break;]
+  case label_2:
+    instructions_2
+    [break;]
+  ...
+  default:
+    instructions_par_defaut
+    [break;]
+}
+
+ +

Pour commencer, le programme recherche (dans l'ordre) une clause case dont le label (ou étiquette) correspond à la valeur de l'expression. Si une telle clause est trouvée, le programme exécutera les instructions associées. Si aucune clause case ne correspond, le programme exécutera les instructions de la clause default si elle est présente. Sinon, le programme continuera avec les instructions qui suivent l'instruction switch. Par convention, la clause default est généralement présentée en dernière bien que ce ne soit pas obligatoire.

+ +

L'instruction optionnelle break, éventuellement contenue pour chaque clause case, permet de ne pas exécuter les instructions pour les cas suivants. Si break n'est pas utilisé, le programme continuera son exécution avec les autres instructions contenues dans l'instruction switch.

+ +

Exemple
+ Dans l'exemple suivant, si fruit vaut "Banane", le programme exécutera les instructions associées. Quand break est rencontré, le programme passe aux instructions décrites après switch. Ici, si break n'était pas présent, les instructions pour le cas "Cerise" aurait également été exécutées.

+ +
switch (fruit) {
+  case "Orange":
+    console.log("Les oranges sont à 60 centimes le kilo.");
+    break;
+  case "Pomme":
+    console.log("Les pommes sont à 32 centimes le kilo.");
+    break;
+  case "Banane":
+    console.log("Les bananes sont à 48 centimes le kilo.");
+    break;
+  case "Cerise":
+    console.log("Les cerises sont à 3€ le kilo.");
+    break;
+  case "Mangue":
+    console.log("Les mangues sont à 50 centimes le kilo.");
+    break;
+  default:
+    console.log("Désolé, nous n'avons pas de " + fruittype + ".");
+}
+console.log("Souhaitez-vous autre chose ?");
+ +
+

Note : Pour plus de détails sur cette instruction, voir la page switch de la référence JavaScript.

+
+ +

Les instructions pour gérer les exceptions

+ +

Il est possible de lever des exceptions avec l'instruction throw et de les gérer (les intercepter) avec des instructions try...catch.

+ + + +

Les types d'exception

+ +

En JavaScript, n'importe quel objet peut être signalé comme une exception. Cependant, afin de respecter certaines conventions et de bénéficier de certaines informations, on pourra utiliser les types destinés à cet effet :

+ + + +

L'instruction throw

+ +

L'instruction throw est utilisée afin de signaler (throw en anglais) une exception. Lorsqu'on signale une exception, on définit une expression qui contient la valeur à renvoyer pour l'exception :

+ +
throw expression;
+
+ +

Il est possible d'utiliser n'importe quelle expression, sans restriction de type. Le fragment de code qui suit illustre les différentes possibilités :

+ +
throw "Erreur2";  //type String
+throw 42;         //type Number
+throw true;       //type Boolean
+throw {toString: function () { return "je suis un objet !"; } };
+
+ +
Note : Il est possible de renvoyer un objet quand on signale une exception. Les propriétés de cet objet pourront être utilisées dans le bloc catch décrit ci-après. Dans l'exemple suivant, on définit un objet monException du type ExceptionUtilisateur, on utilise cet objet dans l'instruction throw.
+ +
// On crée le constructeur pour cet objet
+function ExceptionUtilisateur(message) {
+  this.message = message;
+  this.name = "ExceptionUtilisateur";
+}
+
+// On surcharge la méthode toString pour afficher
+// un message plus explicite (par exemple dans la console)
+ExceptionUtilisateur.prototype.toString = function() {
+  return this.name + ': "' + this.message + '"';
+}
+
+// On crée une instance pour ce type d'objet
+// et on renvoie une exception avec cette instance
+throw new ExceptionUtilisateur("La valeur fournie est trop élevée.");
+ +
+

Note : Pour plus d'informations sur cette instruction, voir la page de la référence JavaScript sur throw.

+
+ +

L'instruction try...catch

+ +

L'instruction try...catch permet de définir un bloc d'instructions qu'on essaye (try en anglais) d'exécuter, ainsi qu'une ou plusieurs instructions à utiliser en cas d'erreur lorsqu'une exception se produit. Si une exception est signalée, l'instruction try...catch permettra de l' « attraper » (catch en anglais) et de définir ce qui se passe dans ce cas.

+ +

L'instruction try...catch se compose d'un bloc try qui contient une ou plusieurs instructions et blocs catch qui contiennent les instructions à exécuter lorsqu'une exception se produit dans le bloc try. Autrement dit, dans la plupart des cas pour le programme, on veut que les instructions du bloc try se déroulent normalement et en cas de problème, on passe le contrôle au bloc catch. Si une instruction contenue dans le bloc try renvoie une exception, le contrôle sera immédiatement transféré au bloc catch. Si aucune exception n'est signalée au sein du bloc try, le bloc catch ne sera pas utilisé. Cette instruction peut comporter un bloc finally qui s'exécute après les blocs try et catch mais avant les instructions suivant l'instruction try...catch.

+ +

Dans l'exemple qui suit, on utilise une instruction try...catch. On définit une fonction qui prend un nombre et renvoie le nom du mois correspondant à ce nombre. Si la valeur fournie n'est pas comprise entre 1 et 12, on signale une exception avec la valeur "NuméroMoisInvalide". Lorsque cette exception est gérée dans le bloc catch, la variable nomMois recevra la valeur "inconnu".

+ +
function getNomMois(numMois) {
+  numMois = numMois - 1; // On décale de 1 car les indices du tableaux commencent à 0
+  var mois = ["Janvier", "Février", "Mars", "Avril" ,"Mai", "Juin", "Juillet",
+              "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
+  if (mois[numMois] != null) {
+    return mois[numMois];
+  } else {
+    throw "NuméroMoisInvalide";  // Ici on utilise l'instruction throw
+  }
+}
+
+try { // les instructions à essayer si tout se passe bien
+  nomMois = getNomMois(maVarMois); // La fonction peut renvoyer une exception
+} catch (e) {
+  nomMois = "inconnu";
+  gestionErreurLog(e); // on gère l'erreur avec une fonction
+}
+
+ +

Le bloc catch

+ +

Un bloc catch peut être utilisé afin de gérer les exceptions pouvant être générées par les instructions du bloc try.

+ +
catch (ident) {
+  statements
+}
+
+ +

Le bloc catch définit un identifiant (ident dans le fragment de code précédent) qui contiendra la valeur passée par l'instruction throw. Cet identifiant peut être utilisé afin de récupérer des informations sur l'exception qui a été signalée. Le moteur JavaScript crée cet identifiant lorsque le contrôle passe au bloc catch. L'identifiant ne « vit » qu'à l'intérieur du bloc catch et une fois que l'exécution du bloc catch est terminée, l'identifiant n'est plus disponible.

+ +

Dans l'exemple suivant, le code renvoie une exception. Lorsque celle-ci est signalée, le contrôle passe au bloc catch.

+ +
try {
+  throw "monException"; // on génère une exception
+} catch (e) {
+  // les instructions utilisées pour gérer les exceptions
+  enregistrerErreurs(e); // on passe l'objet représentant l'exception à une fonction utilisée pour gérer les erreurs
+}
+
+ +
+

Note : Pour plus d'informations sur cette instruction, voir la page de la référence JavaScript sur try...catch.

+
+ +
+

Note : Quand on souhaite afficher des erreurs dans la console, on privilégiera console.error() plutôt que console.log(). En effet, cette première méthode est plus adaptée et indiquera plus d'informations.

+
+ +

Le bloc finally

+ +

Le bloc finally contient les instructions à exécuter après les blocs try et catch mais avant l'instruction suivant le try...catch...finally.

+ +

Le bloc finally est exécuté dans tous les cas, qu'une exception ait été levée ou non. Si une exception est signalée et qu'il n'y a pas de bloc catch pour la gérer, les instructions du bloc finally seront tout de même exécutées.

+ +

Le bloc finally peut être utilisé afin de finir proprement l'exécution malgré une exception. On peut, par exemple, devoir libérer une ressource, ou fermer un flux, etc. Dans l'exemple suivant, on écrit dans un fichier, si une exception se produit lors de l'écriture, on utilisera le bloc finally afin de bien fermer le flux vers le fichier avant la fin du script.

+ +
ouvrirFichier();
+try {
+  écrireFichier(données); // Une erreur peut se produire
+} catch(e) {
+  gérerException(e); // On gère le cas où on a une exception
+} finally {
+  fermerFichier(); // On n'oublie jamais de fermer le flux.
+}
+
+ +

Si le bloc finally renvoie une valeur, cette valeur sera considérée comme la valeur de retour pour tout l'ensemble try-catch-finally, quel que soient les instructions return éventuellement utilisées dans les blocs try et catch :

+ +
function f() {
+  try {
+    console.log(0);
+    throw "bug";
+  } catch(e) {
+    console.log(1);
+    return true; // Cette instruction est bloquée jusqu'à la fin du bloc finally
+    console.log(2); // Ne pourra jamais être exécuté
+  } finally {
+    console.log(3);
+    return false; // On surcharge l'instruction "return" précédente
+    console.log(4); // Ne pourra jamais être exécuté
+  }
+  // "return false" est exécuté
+
+  console.log(5); // Ne pourra jamais être exécuté
+}
+f(); // affiche 0, 1, 3 puis renvoie false
+
+ +

Lorsqu'on surcharge les valeurs de retour avec le bloc finally, cela s'applique également aux exceptions qui sont levées (ou retransmises) au sein du bloc catch :

+ +
function f() {
+  try {
+    throw "problème";
+  } catch(e) {
+    console.log('"problème" interne intercepté');
+    throw e; // cette instruction est mise en attente
+             // tant que le bloc finally n'est pas fini
+  } finally {
+    return false; // surcharge le "throw" précédent
+  }
+  // "return false" est exécuté à ce moment
+}
+
+try {
+  f();
+} catch(e) {
+  // ce bloc n'est jamais utilisé car le throw
+  // utilisé dans le bloc catch a été surchargé
+  // par l'instruction return de finally
+  console.log('"problème" externe intercepté');
+}
+
+// Sortie
+// "problème" interne attrapé
+ +

Imbriquer des instructions try...catch

+ +

Il est possible d'imbriquer une ou plusieurs instructions try...catch. Si une instruction try...catch imbriquée ne comporte pas de bloc catch, elle doit contenir une instruction finally et le bloc catch de l'instruction try...catch englobante sera utilisé si jamais il y a une exception. Pour plus de détails, voir la page sur l'instruction try...catch.

+ +

Utiliser les objets Error

+ +

En fonction du type d'erreur qui est créée, on pourra utiliser les propriétés name et message afin d'obtenir plus d'informations. Généralement on a name qui fournit le type d'erreur rencontrée (ex : DOMException ou Error). La propriété message, quant à elle fournit un message descriptif de l'erreur (qu'on utilisera généralement lorsqu'on voudra convertir/afficher le texte correspondant à une erreur).

+ +

Si vous construisez des erreurs, vous pouvez utiliser le constructeur Error afin de disposer de ces propriétés. Ainsi, on pourra avoir :

+ +
function causerErreurs() {
+  if (toutEstSourceDErreurs()) {
+    throw (new Error('mon message'));
+  } else {
+    générerUneAutreErreur();
+  }
+}
+....
+try {
+  causerErreurs();
+} catch (e) {
+  console.error(e.name);// affiche 'Error'
+  console.erro(e.message); // affiche 'mon message' ou un message d'erreur JavaScript
+}
+ +

{{PreviousNext("Web/JavaScript/Guide/Types_et_grammaire", "Web/JavaScript/Guide/Boucles_et_itération")}}

diff --git "a/files/fr/web/javascript/guide/expressions_et_op\303\251rateurs/index.html" "b/files/fr/web/javascript/guide/expressions_et_op\303\251rateurs/index.html" new file mode 100644 index 0000000000..fc922c49ce --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_et_op\303\251rateurs/index.html" @@ -0,0 +1,934 @@ +--- +title: Expressions et opérateurs +slug: Web/JavaScript/Guide/Expressions_et_Opérateurs +tags: + - Débutant + - Expressions + - Guide + - JavaScript + - Operators +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Fonctions", "Web/JavaScript/Guide/Nombres_et_dates")}}

+ +

Ce chapitre décrit les expressions et les opérateurs en JavaScript, il inclut des notions sur les opérateurs d'affectation, de comparaison, les opérateurs arithmétiques, binaires, logiques, ceux qui s'appliquent sur les chaînes de caractères ainsi que les opérateurs spéciaux.

+ +

Une liste complète et détaillée des opérateurs JavaScript est disponible dans la référence JavaScript.

+ +

Opérateurs

+ +

JavaScript possède différents types d'opérateurs. Cette section décrit les opérateurs et certaines informations sur les priorités entre opérateurs.

+ + + +

JavaScript utilise des opérateurs binaires et unaires, ainsi qu'un opérateur ternaire spécial (l'opérateur conditionnel). Un opérateur binaire utilise deux opérandes, un précédant l'opérateur et un lui succédant :

+ +
opérande1 opérateur opérande2
+
+ +

Par exemple : « 3+4 » ou « x*y ».

+ +

Un opérateur unaire ne nécessite qu'un opérande, avant ou après l'opérateur :

+ +
opérateur opérande
+ +

ou

+ +
opérande opérateur
+ +

Comme « x++ » ou « ++x ».

+ +

Opérateurs d'affectation

+ +

Un opérateur d'affectation assigne une valeur à son opérande gauche, valeur basée sur celle de l'opérande droit. L'opérateur d'affectation simple est le signe égal (=), il assigne la valeur de l'opérande droit à l'opérande gauche. Autrement dit, avec « x = y » on affecte la valeur y à x.

+ +

D'autres opérateurs d'affectation sont des raccourcis correspondant à certaines opérations composées, ils sont énumérés dans le tableau qui suit :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Opérateurs d'affectation
NomOpérateur composéSignification
Affectationx = yx = y
Affectation après additionx += yx = x + y
Affectation après soustractionx -= yx = x - y
Affectation après multiplicationx *= yx = x * y
Affectation après divisionx /= yx = x / y
Affectation du restex %= yx = x % y
Affectation après exponentiation{{experimental_inline}}x **=yx = x ** y
Affectation après décalage à gauchex <<= yx = x << y
Affectation après décalage à droitex >>= yx = x >> y
Affectation après décalage à droite non signéx >>>= yx = x >>> y
Affectation après ET binairex &= yx = x & y
Affectation après OU exclusif binairex ^= yx = x ^ y
Affectation après OU binairex |= yx = x | y
+ +

Décomposition

+ +

Lors d'affectations plus complexes, on peut utiliser l'affectation par décomposition. C'est une expression qui permet d'extraire des données depuis des tableaux ou des objets avec une syntaxe symétrique de littéraux de tableaux ou d'objets pour affecter des variables.

+ +
var toto = ["un", "deux", "trois"];
+
+// sans décomposition
+var un = toto[0];
+var deux = toto[1];
+var trois = toto[2];
+
+// avec la décomposition
+var [un, deux, trois] = toto;
+ +

Opérateurs de comparaison

+ +

Un opérateur de comparaison compare ses deux opérandes et renvoie un valeur booléenne correspondant au résultat de la comparaison (vraie ou fausse). Les opérandes peuvent être des nombres, des chaînes de caractères, des booléens ou des objets. Les chaînes de caractères sont comparées selon l'ordre lexicographique usuel en utilisant les valeurs Unicode. Dans la plupart des cas, si les deux opérandes ne sont pas du même type, JavaScript tentera de les convertir vers un type approprié. Cette méthode aboutira souvent à une comparaison numérique. Les seules exceptions à cette conversion implicite sont les opérateurs === et !== , qui testent des égalités et inégalités strictes. Ces opérateurs n'effectuent pas de conversion de type. Le tableau qui suit décrit les opérateurs de comparaisons relativement à ce fragment de code :

+ +
var var1 = 3;
+var var2 = 4;
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Opérateurs de comparaison
OpérateurDescriptionExemples qui renvoient true
Égalité (==)Renvoie true si les opérandes sont égaux après conversion en valeurs de mêmes types.3 == var1 +

"3" == var1

+ 3 == '3'
Inégalité (!=)Renvoie true si les opérandes sont différents.var1 != 4
+ var2 != "3"
Égalité stricte (===)Renvoie true si les opérandes sont égaux et de même type. Voir {{jsxref("Object.is","Object.is()")}} et égalité de type en JavaScript.3 === var1
Inégalité stricte (!==)Renvoie true si les opérandes ne sont pas égaux ou s'ils ne sont pas de même type.var1 !== "3"
+ 3 !== '3'
Supériorité stricte (>)Renvoie true si l'opérande gauche est supérieur (strictement) à l'opérande droit.var2 > var1
+ "12" > 2
Supériorité ou égalité (>=)Renvoie true si l'opérande gauche est supérieur ou égal à l'opérande droit.var2 >= var1
+ var1 >= 3
Infériorité stricte (<)Renvoie true si l'opérande gauche est inférieur (strictement) à l'opérande droit.var1 < var2
+ "2" < "12"
Infériorité ou égalité (<=)Renvoie true si l'opérande gauche est inférieur ou égal à l'opérande droit.var1 <= var2
+ var2 <= 5
+ +
+

Note : => n'est pas un opérateur. Il s'agit de la notation utilisée pour les fonctions fléchées.

+
+ +

Opérateurs arithmétiques

+ +

Les opérateurs arithmétiques ont pour opérandes des valeurs numériques (des littéraux ou des variables) et renvoient une valeur numérique. Les opérateurs arithmétiques standards sont l'addition (+), la soustraction (-), la multiplication (*), et la division (/). Ces opérateurs fonctionnent comme pour la plupart des langages de programmation lorsqu'ils sont utilisés avec des nombres décimaux (on notera que la division par zéro a pour résultat {{jsxref("Infinity")}}). Ainsi :

+ +
1 / 2; // 0.5
+1 / 2 == 1.0 / 2.0; // true
+
+ +

En plus des opérations arithmétiques standards (+,-,*,/), JavaScript fournit également d'autres opérateurs arithmétiques, listés dans le tableau qui suit :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Opérateurs arithmétiques
OpérateurDescriptionExemple
Reste (%)
+  
Opérateur binaire. Renvoie le reste entier de la division entre les deux opérandes.12 % 5 renvoie 2.
Incrément (++)Opérateur unaire. Ajoute un à son opérande. S'il est utilisé en préfixe (++x), il renvoie la valeur de l'opérande après avoir ajouté un, s'il est utilisé comme opérateur de suffixe (x++), il renvoie la valeur de l'opérande avant d'ajouter un.Si x vaut 3, ++x incrémente x à 4 et renvoie 4, x++ renvoie 3 et seulement ensuite ajoute un à x.
Décrément (--)Opérateur unaire. Il soustrait un à son opérande. Il fonctionne de manière analogue à l'opérateur d'incrément.Si x vaut 3, --x décrémente x à 2 puis renvoie2, x-- renvoie 3 puis décrémente la valeur de x.
Négation unaire (-)Opérateur unaire. Renvoie la valeur opposée de l'opérande.Si x vaut 3, alors -x renvoie -3.
Plus unaire (+)Opérateur unaire. Si l'opérande n'est pas un nombre, il tente de le convertir en une valeur numérique. +

+"3" renvoie 3.

+ +

+true renvoie 1.

+
Opérateur d'exponentiation (**) (puissance) {{experimental_inline}}Calcule un nombre (base) élevé à une puissance donnée (soit basepuissance) +

2 ** 3 renvoie 8

+ +

10 ** -1 renvoie 0.1

+
+ +

Opérateurs binaires

+ +

Les opérateurs binaires voient leurs opérandes comme des ensembles de 32 bits (des zéros et des uns), et non pas comme des nombres décimaux, octaux ou hexadécimaux. Ainsi, le nombre décimal neuf aura une représentation binaire de 1001. Les opérateurs binaires effectuent des opérations sur des représentations binaires mais renvoies des valeurs numériques JavaScript standards.

+ +

Le tableau qui suit résume les opérateurs binaires JavaScript :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Opérateurs binaires
OpérateurUtilisationDescription
AND (ET) binairea & bRenvoie un 1 à chaque position binaire pour laquelle les bits des deux opérandes sont à 1.
OR (OU) binairea | bRenvoie un zéro à chaque position binaire pour laquelle au moins un des bits des deux opérandes est à 0.
XOR (OU exclusif) binairea ^ bRenvoie un zéro à chaque position binaire pour laquelle les bits sont les mêmes (et un 1 pour chacun des bits qui est différent).
NOT (NON) binaire~ aInverse les bits de l'opérande.
Décalage binaire à gauchea << bDécale la représentation binaire de b bits sur la gauche et complète avec des zéros à droite.
Décalage binaire à droitea >> bDécale la représentation binaire de b bits sur la droite en ignorant les bits perdus.
Décalage binaire à droite en complétant avec des zérosa >>> bDécale la représentation binaire de b bits sur la droite en ignorant les bits perdus et ajoute des zéros sur la gauche.
+ +

Opérateurs binaires logiques

+ +

Les opérateurs binaires logiques fonctionnent de cette façon :

+ + + +

Le chiffre neuf est par exemple représenté comme 1001, et le nombre quinze comme 1111. Ainsi, quand les opérateurs binaires sont appliqués sur ces valeurs, on a les résultats qui suivent :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Exemples utilisant les opérateurs binaires
ExpressionRésultatDescription binaire
15 & 991111 & 1001 = 1001
15 | 9151111 | 1001 = 1111
15 ^ 961111 ^ 1001 = 0110
~15-16~00000000...00001111 = 11111111...11110000
~9-10~00000000...00001001 = 11111111...11110110
+ +

Il faut remarquer que tous les bits sont échangés lorsque l'opérateur binaire NOT est utilisé. Il est donc utile de savoir que les valeurs dont le bit le plus fort (le plus à gauche) vaut 1 sont des nombres négatifs (représentation en complément à deux). L'évaluation de ~x aura le même résultat que l'évaluation de -x - 1.

+ +

Opérateurs binaires de décalage

+ +

Les opérateurs binaires de décalage utilisent deux opérandes : le premier indiquant la quantité à décaler et le second indiquant de combien de bits on décale le premier opérande. La direction du décalage est spécifiée grâce à l'opérateur.

+ +

Les opérateurs binaires de décalage convertissent leurs opérandes en entiers sur 32 bits et renvoient un résultat dont le type est le même que l'opérande gauche.

+ +

Les opérateurs de décalage sont énumérés dans le tableau qui suit.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Opérateurs binaires de décalage
OpérateurDescriptionExemple
Décalage à gauche (<<)Cet opérateur décale le premier opérande d'un nombre de bits donné sur la gauche. Les bits en trop sont ignorés et des bits à zéro sont introduits à droite.9<<2 renvoie 36, car 1001, décalé de 2 bits à gauche, devient  100100, dont la représentation en base 10 est  36.
Décalage à droite avec propagation du signe (>>)Cet opérateur décale le premier opérande d'un nombre de bits donné sur la droite. Les bits en trop sont ignorés et des bits correspondants au bit de signe sont introduits à gauche.9>>2 renvoie 2, car 1001, décalé de 2 bits à droite, devient 10 représentant 2. De même  -9>>2 renvoie -3, car le signe est préservé.
Décalage à droite avec zéros (>>>)Cet opérateur décale le premier opérande d'un nombre de bits donné sur la droite. Les bits en trop sont ignorés et des bits à 0 sont introduits à gauche.19>>>2 renvoie 4, car 10011, décalé de 2 bits, devient 100 qui représente 4. Pour les nombres positifs, cet opérateur et l'opérateur précédent renvoient les mêmes résultats.
+ +

Opérateurs logiques

+ +

Les opérateurs logiques sont généralement utilisés avec des valeurs booléennes. Dans ce cas, il renvoient une valeur booléenne. Les opérateurs && et || renvoient en fait une valeurs d'un des opérandes et si ces opérateurs sont utilisés avec des valeurs non-booléennées, ils pourront renvoyer une valeur non-booléenne. Les opérateurs logiques sont décrits dans le tableau qui suit.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Opérateurs logiques
OpérateurUsageDescription
ET logique (&&)expr1 && expr2Renvoie expr1 s'il peut être converti à false, sinon renvoie expr2. Dans le cas où on utilise des opérandes booléens, && renvoie true si les deux opérandes valent true, false sinon.
OU logique (||)expr1 || expr2Renvoie expr1 s'il peut être converti à true, sinon renvoie expr2. Dans le cas où on utilise des opérandes booléens, || renvoie true si l'un des opérandes vaut true, si les deux valent false, il renvoie false.
NON logique (!)!exprRenvoie false si son unique opérande peut être converti en true, sinon il renvoie true.
+ +

Les exemples d'expressions qui peuvent être converties à false sont celles qui sont évaluées à null, 0, NaN, la chaîne de caractères vide (""), ou undefined.

+ +

Le code qui suit montre des exemples de l'utilisation de l'opérateur logique ET (&&).

+ +
var a1 =   true && true;     // t && t renvoie true
+var a2 =   true && false;    // t && f renvoie false
+var a3 =  false && true;     // f && t renvoie false
+var a4 =  false && (3 == 4); // f && f renvoie false
+var a5 = "Chat" && "Chien";  // t && t renvoie Chien
+var a6 =  false && "Chat";   // f && t renvoie false
+var a7 = "Chat" && false;    // t && f renvoie false
+
+ +

Les exemples suivants montrent l'utilisation de l'opérateur logique OU (||).

+ +
var o1 =   true || true;     // t || t renvoie true
+var o2 =  false || true;     // f || t renvoie true
+var o3 =   true || false;    // t || f renvoie true
+var o4 =  false || (3 == 4); // f || f renvoie false
+var o5 = "Chat" || "Chien";  // t || t renvoie Chat
+var o6 =  false || "Chat";   // f || t renvoie Chat
+var o7 = "Chat" || false;    // t || f renvoie Chat
+
+ +

Les exemples suivants montrent l'utilisation de l'opérateur logique NON (!).

+ +
var n1 = !true;   // !t renvoie false
+var n2 = !false;  // !f renvoie true
+var n3 = !"Chat"; // !t renvoie false
+
+ +

Evaluation rapide

+ +

Les expressions logiques sont évaluées de gauche à droite. Cette évaluation utilise des tests pour savoir s'il est possible d'utiliser des « raccourcis » correspondant aux règles suivantes :

+ + + +

Les règles logiques garantissent la validité de ces évaluations, il faut noter que le second opérande n'est pas du tout évalué, empêchant ainsi les effets de bords cachés, liés à cette évaluation.

+ +

Opérateurs de chaînes de caractères

+ +

En plus des opérateurs de comparaisons qui peuvent être utilisés sur des chaînes de caractères, il existe l'opérateur de concaténation (+) permettant de concaténer deux chaînes de caractères. Le résultat de cette opération est la fusion des deux opérandes en une même chaîne de caractères. Ainsi :

+ +
console.log("ma " + "chaîne"); // affichera "ma chaîne" dans la console
+ +

L'opérateur court += peut également être utilisé pour concaténer des chaînes. Par exemple :

+ +
var maChaîne = "alpha";
+maChaîne += "bet"; // l'expression sera évaluée en "alphabet"
+                   // et cette valeur sera affectée à maChaîne
+ +

Opérateur conditionnel ternaire

+ +

L'opérateur conditionnel est le seul opérateur JavaScript qui utilise trois opérandes. L'expression utilisant l'opérateur peut prendre une valeur parmi deux selon une condition donnée. Cet opérateur s'utilise avec la syntaxe suivante :

+ +
condition ? val1 : val2
+
+ +

Si condition vaut true, l'opérateur vaudra val1. Sinon il vaudra val2. Il est possible d'utiliser l'opérateur conditionnel aux mêmes endroits qu'un opérateur standard.

+ +

On peut par exemple avoir :

+ +
var statut = (âge >= 18) ? "adulte" : "mineur";
+
+ +

Cette instruction assigne la valeur "adulte" à la variable status si la variable âge est supérieure ou égale à 18. Sinon, on lui affecte la valeur "mineur".

+ +

La virgule comme opérateur

+ +

L'opérateur virgule (,) évalue ses deux opérandes et renvoie la valeur du second opérande. Cet opérateur est principalement utilisé dans les boucles for pour permettre à plusieurs variables d'être modifiées à chaque itération de la boucle.

+ +

Ainsi, si on a un tableau à 2 dimensions avec 10 lignes et colonnes, on peut utiliser la virgule comme opérateur pour incrémenter deux variables à la fois. Le code qui suit imprime les valeurs contenues sur la diagonale du tableau :

+ +
var x = [0,1,2,3,4,5,6,7,8,9]
+var a = [x, x, x, x, x];
+
+for (var i = 0, j = 9; i <= j; i++, j--)
+  console.log("a[" + i + "][" + j + "]= " + a[i][j]);
+
+ +

Opérateurs unaires

+ +

delete

+ +

L'opérateur delete supprime un objet, une propriété d'un objet ou un élément d'un tableau à partir de sa position dans le tableau. La syntaxe de cet opérateur est la suivante :

+ +
delete monObjet;
+delete monObjet.propriété;
+delete monObjet[index];
+delete propriété; // uniquement valide au sein d'une instruction with
+
+ +

où on a monObjet qui est le nom de l'objet, propriété qui est une propriété existante et index un entier indiquant la position d'un élément dans un tableau.

+ +

La quatrième instruction n'est valide qu'au sein d'une instruction with et permet de supprimer une propriété d'un objet.

+ +

Il est possible d'utiliser l'opérateur delete pour supprimer les variables déclarées implicitement mais pas celles déclarées avec var. Si l'opérateur fonctionne correctement, il change la propriété ou l'élément vers la valeur undefined. L'opérateur delete renvoie true si l'opération de suppression est possible, false sinon.

+ +
x = 42;
+var y = 43;
+monobj = new Number();
+monobj.h = 4;    // création de la propriété h
+delete x;        // renvoie true (suppression possible si déclaration implicite)
+delete y;        // renvoie false (suppression impossible si déclaration avec var si la variable n'est pas une propriété)
+delete Math.PI;  // renvoie false (suppression impossible pour les propriétés pré-définies)
+delete monobj.h; // renvoie true (suppression possible des propriétés définies par l'utilisateur)
+delete monobj;   // renvoie true (suppression possible si déclaration implicite)
+
+ +
Suppression d'éléments d'un tableau
+ +

Lorsqu'on supprime un élément d'un tableau, la longueur du tableau n'est pas modifiée. Ainsi, si on supprime a[3], a[4] restera a[4] (même position et valeur) alors que a[3] sera undefined.

+ +

Lorsque l'opérateur delete supprime un élément d'un tableau, cet élément n'appartient plus au tableau. Dans l'exemple qui suit, arbres[3] est supprimé mais il est toujours accessible et renvoie undefined.

+ +
var arbres = new Array("sequoia", "laurier", "cèdre", "chêne", "érable");
+delete arbres[3];
+if (3 in arbres) {
+  // Ceci ne sera pas exécuté
+}
+
+ +

Pour qu'un élément continue à exister mais qu'il vaille undefined, on utilisera le mot-clé undefined plutôt que l'opérateur delete. Dans l'exemple qui suit, arbres[3] est modifié pour valoir undefined et l'élément du tableau continue à exister :

+ +
var arbres = new Array("sequoia", "laurier", "cèdre", "chêne", "érable");
+arbres[3] = undefined;
+if (3 in arbres) {
+  // Ceci sera exécuté
+}
+
+ +

typeof

+ +

L'opérateur typeof peut être utilisé de deux façons distinctes :

+ +
    +
  1. +
    typeof opérande
    +
  2. +
  3. +
    typeof (opérande)
    +
    +
  4. +
+ +

L'opérateur typeof renvoie une chaîne de caractères indiquant le type de l'opérande (qui n'est pas évalué). opérande correspond à la chaîne de caractère, la variable, le mot-clé ou l'objet dont on souhaite renvoyer le type. L'utilisation des parenthèses est facultative.

+ +

Soient les définitions de variables suivantes :

+ +
var maFonction = new Function("5 + 2");
+var forme = "round";
+var taille = 1;
+var toto = ["Pomme", "Poire", "Orange"];
+var jour = new Date();
+
+ +

L'opérateur typeof renverra les résultats suivants :

+ +
typeof maFonction; // renvoie "function"
+typeof forme;      // renvoie "string"
+typeof taille;     // renvoie "number"
+typeof toto;       // renvoie "object"
+typeof jour;       // renvoie "object"
+typeof inexistant; // renvoie "undefined"
+
+ +

En ce qui concerne les mots-clés true et null, l'opérateur typeof renvoie les résultats suivants :

+ +
typeof true; // renvoie "boolean"
+typeof null; // renvoie "object"
+
+ +

Pour une chaîne de caractères ou un nombre, typeof renvoie les résultats suivants :

+ +
typeof 62;            // renvoie "number"
+typeof 'Hello world'; // renvoie "string"
+
+ +

L'opérateur typeof, lorsqu'il est utilisé avec des propriétés, renvoie le type de valeur contenue dans la propriété :

+ +
typeof document.lastModified; // renvoie "string"
+typeof window.length;         // renvoie "number"
+typeof Math.LN2;              // renvoie "number"
+
+ +

Pour les méthodes et les fonctions, l'opérateur typeof renvoie les résultats suivants :

+ +
typeof blur;        // renvoie "function"
+typeof eval;        // renvoie "function"
+typeof parseInt;    // renvoie "function"
+typeof shape.split; // renvoie "function"
+
+ +

Pour les objets pré-définis, l'opérateur typeof fonctionne ainsi :

+ +
typeof Date;     // renvoie "function"
+typeof Function; // renvoie "function"
+typeof Math;     // renvoie "object"
+typeof Option;   // renvoie "function"
+typeof String;   // renvoie "function"
+
+ +

void

+ +

L'opérateur void peut être utilisé de deux façons :

+ +
    +
  1. +
    void (expression)
    +
    +
  2. +
  3. +
    void expression
    +
    +
  4. +
+ +

L'opérateur void indique qu'une expression doit être évaluée sans retourner de valeur. expression étant une expression JavaScript à évaluer. Les parenthèses sont facultatives mais les utiliser permet d'avoir une meilleur lisibilité du code.

+ +

L'opérateur void peut être utilisé pour spécifier une expression comme un lien hypertexte, l'expression est évaluée mais n'est pas chargée à la place du document actuel.

+ +

Le fragment de code  qui suit crée un lien hypertexte qui ne fait rien lorsque l'utilisateur clique dessus. Lorsqu'on clique sur le lien, void(0) est évalué à undefined, n'ayant aucun effet.

+ +
<A HREF="javascript:void(0)">Cliquer ici pour ne rien faire</A>
+
+ +

Le code suivant crée un lien hypertexte qui envoie un formulaire lorsque l'utilisateur clique dessus.

+ +
<A HREF="javascript:void(document.form.submit())">
+Cliquer ici pour envoyer</A>
+ +

Opérateurs relationnels

+ +

Un opérateur relationnel compare ses opérandes et renvoie une valeur booléenne selon que le résultat de la comparaison est vrai ou faux.

+ +

in

+ +

L'opérateur in renvoie true si la propriété indiquée fait partie de l'objet donné. Cet opérateur s'utilise avec la syntaxe suivante :

+ +
nomOuNumeroPropriete in monObjet
+
+ +

avec nomOuNumeroPropriete qui est une chaîne de caractères, une expression numérique ou un symbole correspondant au nom d'une propriété ou un indice de tableau, monObjet est le nom d'un objet.

+ +

Les exemples qui suivent utilisent cet opérateur in.

+ +
// Tableaux
+var arbres = new Array("sequoia", "laurier", "cèdre", "chêne", "érable");
+0 in arbres;         // renvoie true
+3 in arbres;         // renvoie true
+6 in arbres;         // renvoie false
+"laurier" in arbres; // renvoie false (l'opérateur se base sur l'indice et pas
+                     // sur la valeur)
+"length" in arbres;  // renvoie true (length est une propriété d'un objet Array)
+
+// Objets pré-définis
+"PI" in Math;         // renvoie true
+var myString = new String("coral");
+"length" in myString; // renvoie true
+
+// Objets définis par l'utilisateur
+var maVoiture = {fabricant: "Honda", modèle: "Accord", year: 1998};
+"fabricant" in maVoiture; // renvoie true
+"modèle" in maVoiture;    // renvoie true
+
+ +

instanceof

+ +

L'opérateur instanceof renvoie true si l'objet donné est du type spécifié. Cet opérateur s'utilise avec la syntaxe suivante :

+ +
nomObjet instanceof typeObjet
+
+ +

avec nomObjet qui est le nom de l'objet dont on souhaite comparer le type à typeObjet, typeObjet étant un type d'objet tel que {{jsxref("Date")}} ou {{jsxref("Array")}}.

+ +

instanceof peut être utilisé pour confirmer le type d'un objet pendant l'exécution. Ainsi, on peut gérer les exceptions en prévoyant différents cas pour différents types d'exception éventuellement levées.

+ +

Dans l'exemple qui suit, le code utilise l'opérateur instanceof afin de déterminer si jour est un objet Date. C'est le cas, les instructions contenues dans le bloc après l'instruction if sont donc exécutées.

+ +
var jour = new Date(2007, 01, 22);
+if (jour instanceof Date) {
+  // instructions à exécuter
+}
+
+ +

Précédence des opérateurs

+ +

La précédence des opérateurs indique l'ordre dans lequel ils sont appliqués lors de l'évaluation d'une expression. L'utilisation de parenthèses permet de surcharger la relation de précédence.

+ +

Le tableau qui suit décrit les précédences des opérateurs, dans l'ordre décroissant.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Précédence des opérateurs
Type d'opérateurOpérateurs individuels
membre. []
appel/création d'instance() new
négation/incrémentation! ~ - + ++ -- typeof void delete
multiplication/division* / %
addition/soustraction+ -
décalage binaire<< >> >>>
relationnel< <= > >= in instanceof
égalité== != === !==
ET binaire&
OU exclusif binaire^
OU binaire|
ET logique&&
OU logique||
conditionnel?:
assignation= += -= *= /= %= <<= >>= >>>= &= ^= |=
virgule,
+ +

Une version plus détaillée de cette table peut être trouvée dans la référence JavaScript.

+ +

Expressions

+ +

Un expression correspond à une unité de code valide qui est résolue en une valeur.

+ +

D'un point de vue syntaxique, toute expression valide se résout en une valeur. D'un point de vue conceptuel cependant, il y a deux types d'expressions : celles avec des effets de bord (qui, par exemple, affectent une valeur à une variable) et celles qui, d'une certaine façon, sont évaluées et sont résolues en une valeur.

+ +

L'expression x = 7 affecte une valeur (premier type). Dans celle-ci, on utilise l'opérateur = pour affecter la valeur 7 à la variable x. L'expression elle-même est évaluée à 7.

+ +

Le code 3 + 4 correspond au second type d'expression. On utilise ici l'opérateur + pour ajouter trois à quatre sans affecter le résultat (7) à une variable.

+ +

Les expressions JavaScript peuvent être rangées selon différentes catégories :

+ + + +

Expressions primaires

+ +

Ces expressions correspondent aux mots-clés et aux expressions générales en JavaScript.

+ +

this

+ +

Le mot-clé this permet de faire référence à l'objet courant. En général, on l'utilise au sein d'une méthode pour faire référence à l'objet qui a utilisé la méthode. Il s'utilise de cette façon :

+ +
this["nomPropriété"]
+this.nomPropriété
+ +

Soit une fonction qui valide un objet si sa propriété value est comprise entre deux valeurs :

+ +
function valide(obj, valMin, valMax){
+  if ((obj.value < valMin) || (obj.value > valMax))
+    console.log("Valeur incorrecte !");
+}
+
+ +

Il est possible d'appeler valide pour chaque gestionnaire d'événement onChange des éléments du formulaire, et d'utiliser le mot-clé this pour passer l'élément même en argument :

+ +
<p>Entrez un nombre entre 18 et 99 :</p>
+<input type="text" nom="age" size=3 onChange="valide(this, 18, 99);">
+
+ +

Opérateur de groupement

+ +

L'opérateur de groupement ( ) permet de contrôler la précédence de l'évaluation dans les expressions. On peut ainsi forcer l'évaluation d'une addition avant l'évaluation d'une multiplication ou d'une division.

+ +
var a = 1;
+var b = 2;
+var c = 3;
+
+// précédence par défaut
+a + b * c;   // 7
+// ce qui correspond à :
+a + (b * c); // 7
+
+// on peut utiliser l'opérateur
+// pour effectuer l'addition en premier
+(a + b) * c;   // 9
+
+// ce qui équivaut à :
+a * c + b * c; // 9
+
+ +

Expressions vers la gauche

+ +

Les valeurs à gauches de ces expressions sont la cible d'une affectation.

+ +

new

+ +

L'opérateur new permet de créer une instance d'un objet défini par l'utilisateur ou d'un objet dont le type est un des types d'objets natifs. Cet opérateur utilise la syntaxe suivante :

+ +
var nomObjet = new typeObjet([param1, param2, ..., paramN]);
+
+ +

super

+ +

Le mot-clé super est utilisé afin d'appeler des fonctions disponibles sur un objet parent. Il peut notamment être utilisé avec les classes pour appeler le constructeur parent.

+ +
super([arguments]); // invoque le constructeur parent
+super.functionParent([arguments]);
+
+ +

Opérateur de décomposition

+ +

L'opérateur de décomposition permet de développer une expression là où plusieurs argument (pour les appels de fonction) ou plusieurs éléments (pour les littéraux de tableaux) sont attendus.

+ +

Par exemple, si on a tableau et qu'on souhaite créer un nouveau tableau qui contient l'ancien, on peut soit utiliser une combinaison des méthodes push, splice, concat, soit utiliser la syntaxe de décomposition qui s'avère plus concise :

+ +
var parts = ['shoulders', 'knees'];
+var lyrics = ['head', ...parts, 'and', 'toes'];
+ +

L'opérateur de décomposition fonctionne de façon semblable avec les appels de fonction :

+ +
function f(x, y, z) { }
+var args = [0, 1, 2];
+f(...args);
+ +

{{PreviousNext("Web/JavaScript/Guide/Fonctions", "Web/JavaScript/Guide/Nombres_et_dates")}}

diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/assertions/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/assertions/index.html" new file mode 100644 index 0000000000..2802651d49 --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/assertions/index.html" @@ -0,0 +1,106 @@ +--- +title: Assertions +slug: Web/JavaScript/Guide/Expressions_régulières/Assertions +tags: + - Assertions + - Guide + - JavaScript + - RegExp +translation_of: Web/JavaScript/Guide/Regular_Expressions/Assertions +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

Les assertions indiquent les conditions selon lesquelles il est possible d'avoir une correspondance (contenu situé avant la correspondance, situé après ou expressions conditionnelles).

+ +

Types

+ +
+

Note : Le caractère ? peut également être utilisé comme quantificateur.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CaractèresSignification
x(?=y) +

Correspond à 'x' seulement s'il est suivi de 'y'. On appelle cela un test de succession (lookahead).

+ +

Ainsi, /Jack(?=Sparrow)/ correspond à 'Jack' seulement s'il est suivi de 'Sparrow'. /Jack(?=Sparrow|Bauer)/ correspond à 'Jack' seulement s'il est suivi de 'Sparrow' ou de 'Bauer'. Cependant, ni 'Sparrow' ni 'Bauer' ne feront partie de la correspondance.

+
x(?!y) +

Correspond à 'x' seulement si 'x' n'est pas suivi de 'y'.

+ +

Ainsi, /\d+(?!\.)/ correspond à un nombre qui n'est pas suivi par un point, cette expression utilisée avec la chaîne 3.141 correspondra pour '141' mais pas pour '3.141'.

+
(?<=y)x +

Correspond à x seulement si x est précédé par y. C'est ce qu'on appelle une recherche arrière (lookbehind).

+ +

Ainsi /(?<=Jack)Sprat/ correspond à "Sprat" seulement s'il est précédé de "Jack".
+ /(?<=Jack|Tom)Sprat/ correspond à "Sprat" seulement s'il est précédé de "Jack" ou "Tom".
+ Toutefois, "Jack" et "Tom" ne feront pas partie de la correspondance.

+
(?<!y)x +

Correspond à x uniquement si x n'est pas précédé par y (parfois appelée en anglais negated lookbehind).

+ +

Ainsi, /(?<!-)\d+/ correspondra à un nombre seulement si celui-ci n'est pas précédé d'un signe moins.
+ /(?<!-)\d+/.exec('3') cible "3".
+  /(?<!-)\d+/.exec('-3')  ne trouve aucune correspondance car le nombre est précédé d'un signe

+
+ +

Exemples

+ +

Assertion avant (lookahead)

+ +
let regex = /Premier(?= test)/g;
+
+console.log('Premier test'.match(regex)); // [ 'Premier' ]
+console.log('Premier truc'.match(regex)); // null
+console.log("Voici le Premier test de l'année.".match(regex)); // [ 'Premier' ]
+console.log('Voici le Premier truc du mois.'.match(regex)); // null
+
+ +

Assertion avant négative

+ +

L'expression rationnelle /\d+(?!\.)/ permettra de rechercher plusieurs chiffres si ceux-ci ne sont pas suivis d'un point décimal. Ainsi, /\d+(?!\.)/.exec('3.141') trouvera la sous-chaîne "141" mais pas "3."

+ +
console.log(/\d+(?!\.)/g.exec('3.141')); // [ '141', index: 2, input: '3.141' ]
+
+ +

Signification différente de '?!' entre les assertions et les intervalles

+ +

La combinaison de caractères ?! a un sens différent entre les assertions /x(?!y)/ et les intervalles [^?!].

+ +
let orangePasCitron = "Voulez-vous avoir une orange? Oui, je ne veux pas avoir de citron!";
+
+let choixPasCitron = /[^?!]+avoir(?! un citron)[^?!]+[?!]/gi
+console.log(orangePasCitron.match(choixPasCitron)); // [ 'Voulez-vous avoir une orange?' ]
+
+let choixPasOrange = /[^?!]+avoir(?! une orange)[^?!]+[?!]/gi
+console.log(orangePasCitron.match(choixPasOrange)); // [ 'Oui, je ne veux pas avoir de citron!' ]
+
+ +

Assertion arrière (lookbehind)

+ +
let oranges = ['espèce orange A ', 'sorte orange B', 'espèce orange C',];
+
+let especesOranges = oranges.filter( fruit => fruit.match(/(?<=espèce )orange/));
+console.log(especesOranges); // [ 'espèce orange A ', 'espèce orange C' ]
+
diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/classes_de_caract\303\250res/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/classes_de_caract\303\250res/index.html" new file mode 100644 index 0000000000..ce2d02b789 --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/classes_de_caract\303\250res/index.html" @@ -0,0 +1,182 @@ +--- +title: Classes de caractères +slug: Web/JavaScript/Guide/Expressions_régulières/Classes_de_caractères +tags: + - Classes + - Guide + - JavaScript + - RegExp +translation_of: Web/JavaScript/Guide/Regular_Expressions/Character_Classes +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

Les classes de caractères permettent de distinguer différents ensembles de caractères dans les expressions rationnelles (par exemple les chiffres d'une part et les lettres d'autre part).

+ +

Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CaractèresSignification
. +

Par défaut, (Le point) correspond à n'importe quel caractère excepté un caractère de saut de ligne.

+ +

Ainsi, /.n/ correspond à  'un' et 'en' dans "Un baobab nain en cours de  croissance" mais pas à 'nain'.

+ +

Si le marqueur s (dotAll) est utilisé, le point correspondra également aux caractères de saut de ligne.

+ +

Le marqueur m ne modifie pas le comportement du point.

+ +

Attention, si on utilise le point dans un intervalle de caractères, il n'aura plus cette signification spéciale.

+
\d +

Correspond à un chiffre et est équivalent à [0-9].

+ +

Ainsi, /\d/ ou /[0-9]/ correspond à '2' dans "H2O est la molécule de l'eau".

+
\D +

Correspond à tout caractère qui n'est pas un chiffre et est équivalent à [^0-9].

+ +

Ainsi, /\D/ ou /[^0-9]/ correspond à 'H' dans "H2O est la molécule de l'eau".

+
\w +

Correspond à n'importe quel caractère alphanumérique de l'alphabet latin, y compris le tiret bas. C'est équivalent à [A-Za-z0-9_].

+ +

Ainsi, /\w/ correspond à 'l' dans "licorne", à '5' dans "5,28€", et à '3' dans "3D."

+
\W +

Correspond à n'importe quel caractère n'étant pas un caractère de l'alphabet latin ou le tiret bas. Cela est équivalent à [^A-Za-z0-9_].

+ +

Ainsi, /\W/ ou /[^A-Za-z0-9_]/ correspond à '%' dans "50%."

+
\s +

Correspond à un blanc (cela comprend les espace, tabulation, saut de ligne ou saut de page). C'est équivalent à [ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff].

+ +

Ainsi, /\s\w*/ correspond à ' toto' dans "truc toto".

+
\S +

Correspond à un caractère qui n'est pas un blanc. C'est équivalent à [^ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff].

+ +

Ainsi, /\S\w*/ correspond à 'truc' dans "truc toto".

+
\tCorrespond à une tabulation (U+0009).
\rCorrespond à un retour chariot (U+000D).
\nCorrespond à un saut de ligne (U+000A).
\vCorrespond à une tabulation verticale (U+000B).
\fCorrespond à un saut de page (U+000C).
[\b]Correspond pour un retour arrière (U+0008). (À ne pas confondre avec \b, voir les limites).
\0Correspond au caractère NULL (U+0000). Il ne doit pas être suivi d'un autre chiffre car \0<chiffres> est une séquence d'échappement pour les nombres en notation octale (si besoin d'utiliser un chiffre ensuite, on pourra utiliser la forme \x00, cf. ci-après).
\cX +

Correspond au caractère de contrôle où X est une lettre entre A et Z. Correspond au caractèlres de contrôle correspondant entre U+0001-U+001F. Ainsi, /\cM/ correspondra au caractère controle-M au sein d'une chaîne de caractères soit "\r" pour "\r\n".

+
\xhhCorrespond au caractère dont le code hexadécimal est hh (deux chiffres hexadécimaux).
\uhhhhCorrespond au caractère dont le code est hhhh (quatre chiffres hexadécimaux).
\u{hhhh} ou \u{hhhhh}(Uniquement actif quand le marqueur u est activé) Correspond au caractère dont la valeur Unicode est hhhh (en chiffre hexadécimaux).
\ +

La barre oblique inversée indique que le prochain caractère doit être traité spécifiquement ou échappé. Elle se comporte d'une de ces façons :

+ +
    +
  • Pour les caractères normalement traités littéralement, cela indique que le prochain caractère est spécial et qu'il ne doit pas être interprété littéralement. Ainsi, /b/ correspondra à la lettre "b" mais en utilisant la barre oblique inversée devant /\b/, on cherchera une limite de mot.
  • +
  • Pour les caractères spéciaux, la barre indique que le caractère doit être interprété littéralement. Ainsi, "*" est un caractère spécial (un quantificateur qui signifie que le caractère précédent doit être présent 0 ou plusieurs fois) : /a*/ cherchera une correspondance avec 0 ou plusieurs "a". Si on souhaite trouver le caractère * dans une chaîne, on placera la barre oblique inversée devant : on a ainsi /a\*/ qui permet de trouver "a*" dans une chaîne.
  • +
+ +
+

Note : L'échappement vaut également avec la barre oblique inversée. Autrement dit, si on cherche la présence de \ dans une chaîne, on pourra utiliser l'expression /\\/ (où la première barre oblique échape la seconde).

+
+
+ +

Spécifications

+ + + + + + + + + + + + + + + + +
SpécificationÉtatCommentaires
{{SpecName('ES3')}}{{Spec2('ES3')}}Définition initiale. Implémentée avec JavaScript 1.1.
+ +

Compatibilité des navigateurs

+ + + +

{{Compat("javascript.builtins.RegExp.property_escapes")}}

+ +

Voir aussi

+ + diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/groupes_et_intervalles/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/groupes_et_intervalles/index.html" new file mode 100644 index 0000000000..269313a659 --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/groupes_et_intervalles/index.html" @@ -0,0 +1,93 @@ +--- +title: Groupes et intervalles +slug: Web/JavaScript/Guide/Expressions_régulières/Groupes_et_intervalles +tags: + - Groupes + - Guide + - Intervalles + - JavaScript + - RegExp +translation_of: Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

Les groupes et intervalles permettent de représenter des groupes ou des intervalles de caractères dans des expressions rationnelles.

+ +

Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CaractèresSignification
x|y +

Correspond à 'x' ou 'y'.

+ +

Ainsi, /vert|rouge/ correspond à 'vert' dans "feu vert" et à 'rouge' dans "feu rouge".

+
[xyz]
+ [a-c]
Un ensemble de caractère. Ce type de motif correspond pour n'importe quel caractètre présent entre les crochets, y compris les séquences d'échappement. Les caractères spéciaux comme le point (.) et l'astérisque ne sont pas considérés comme spéciaux au sein d'un ensemble et n'ont donc pas besoin d'être échappés. Il est possible de donner un ensemble sur un intervalle de caractères en utilisant un tiret (-), comme le montre l'exemple qui suit.
+
+ Le motif [a-d],  aura les mêmes correspondances que [abcd], correspondant au 'b' de "bulle" et au 'c' de "ciel". Les motifis /[a-z.]+/ et /[\w.]+/ correspondront pour la chaîne entirère : "Adre.ss.e".
+

[^xyz]
+ [^a-c]

+
+ + +

Exclusion d'un ensemble de caractères. Cela correspond à tout ce qui n'est pas compris entre crochets. Il est possible de fournir un intervalle de caractères en utilisant un tiret (-). Les autres règles qui s'appliquent pour l'ensemble de caractères (ci-avant) s'appliquent également ici.

+ +

Par exemple, [^abc] est équivalent à [^a-c]. Ils correspondent à 'u' dans "bulle" et à 'i' dans "ciel".

+ +
+

Note : Le caractère ^ peut également être utilisé afin d'indiquer le début d'un champ.

+
+
(x) +

Correspond à 'x' et garde la correspondance en mémoire. Les parenthèses permettent de capturer l'expression dans un « groupe ».
+
+ Les '(toto)' et '(truc)', dans le motif /(toto) (truc) \1 \2/ correspondent et gardent en mémoire les deux premiers mots de la chaîne de caractère "toto truc toto truc". Les \1 et \2 du motif correspondent respectivement à la première et à la deuxième correspondances pour les sous-chaînes entre parenthèses. Lorsqu'on souhaite effectuer un remplacement, on utilisera $1 et $2 pour faire référence au premier et second groupe et $n pour faire référence au n-ième groupe capturé (ex. ('toto truc'.replace(/(...) (...)/, '$2 $1'). $& fera référence à la chaîne entière).

+ +

Capturing groups have a performance penalty. If you don't need the matched substring to be recalled, prefer non-capturing parentheses (see below).

+ +

String.match() won't return groups if the /.../g flag is set. However, you can still use String.matchAll() to get all matches.

+
\n +

Avec n un entier positif. Cela permet de faire référence à la dernière sous-chaîne qui correspond au n-ième groupe entre parenthèses de l'expression rationnelle (en comptant les parenthèses gauche). Ainsi, /apple(,)\sorange\1/ correspondra à "apple, orange," dans "apple, orange, cherry, peach".

+
(?<Nom>x) +

Correspond à x et nomme la correspondance. Les correspondances associées pourront être retrouvées via le nom indiqué. Les chevrons ('<' et '>') sont obligatoires pour encadrer le nom.

+ +

Ainsi, si on veut extraire la composante de zone d'un numéro de téléphone aux États-Unis, on pourra écrire /\((?<area>\d\d\d)\)/ et récupérer le nombre voulu avec matches.groups.area.

+
(?:x)Correspond à 'x' mais ne garde pas la correspondance en mémoire. Les parenthèses ne capturent pas l'expression et permettent d'utiliser des sous-expressions d'une expression régulière pour travailler plus finement. L'expression /(?:zoo){1,2}/ sans parenthèes non-capturantes les caractères {1,2} ne s'appliqueraient qu'au dernier 'o' de 'zoo'. Avec les parenthèses capturantes, {1,2} s'applique au mot entier 'zoo'.
+ +
+

 Note de compatibilité : Firefox ne prend pas en charge les groupes nommés. Pour plus d'informations, voir le bug correspondant.

+
diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/index.html" new file mode 100644 index 0000000000..94d037bbf2 --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/index.html" @@ -0,0 +1,745 @@ +--- +title: Expressions rationnelles +slug: Web/JavaScript/Guide/Expressions_régulières +tags: + - Guide + - Intermédiaire + - JavaScript + - RegExp +translation_of: Web/JavaScript/Guide/Regular_Expressions +--- +

{{jsSidebar("JavaScript Guide")}}{{PreviousNext("Web/JavaScript/Guide/Formatage_du_texte", "Web/JavaScript/Guide/Collections_indexées")}}

+ +

Les expressions rationnelles sont des motifs utilisés pour correspondre à certaines combinaisons de caractères au sein de chaînes de caractères. En JavaScript, les expressions rationnelles sont également des objets. Ces motifs sont utilisés avec les méthodes {{jsxref("RegExp.exec", "exec")}} et {{jsxref("RegExp.test", "test")}} de {{jsxref("RegExp")}}, et avec les méthodes {{jsxref("String.match", "match")}}, {{jsxref("String.matchAll", "matchAll")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.search", "search")}} et {{jsxref("String.split", "split")}} de {{jsxref("String")}}. Ce chapitre explique comment utiliser les expressions rationnelles en JavaScript (aussi appelées expressions régulières ou « RegExp »).

+ +

Créer une expression rationnelle

+ +

Il est possible de construire une expression rationnelle de deux façons :

+ + + +

Écrire une expression rationnelle

+ +

Le motif d'une expression rationnelle est composé de caractères simples (comme /abc/), ou de caractères simples et spéciaux, comme /ab*c/ ou /Chapitre (\d+)\.\d*/ . Le dernier exemple utilise des parenthèses qui permettent d'avoir une « mémoire ». La correspondance avec le motif contenu entre parenthèses pourra être utilisée par la suite. Ceci est décrit avec ce paragraphe.

+ +

Utiliser des motifs simples

+ +

Les motifs simples sont construits à partir de caractères pour lesquels on souhaite avoir une correspondance directe. Le motif /des/ correspond lorsqu'on observe exactement les caractères 'des' ensemble et dans cet ordre précis. On pourrait utiliser ce motif et détecter une correspondance dans les chaînes suivantes : "J'ai vu des licornes ?" et "Sa description de licorne était superbe" car la chaîne de caractères 'des' y est présente (dans le mot description pour le second exemple). Il n'y aura pas de correspondance avec la chaîne de caractères "Toc toc" car 'des' n'est pas présente.

+ +

Utiliser des caractères spéciaux

+ +

Lorsque le motif à trouver est plus complexe qu'une simple égalité (trouver tous les B, les blancs...), le motif devra contenir des caractères spéciaux. Ainsi, le motif /ab*c/ correspond à toutes les combinaisons de caractères qui possèdent un seul 'a' suivi de zéro ou plusieurs 'b' (l'astérisque utilisée ici signifie que l'élément qui la précède doit être présent zéro ou plusieurs fois) qui sont immédiatement suivis d'un 'c'. Par exemple, la chaîne de caractère "cbbabbbbcdebc" correspond au motif avec la chaîne de caractères 'abbbbc'.

+ +

Les pages suivantes décrivent en détail les caractères spéciaux qui peuvent être utilisés afin de composer une expression rationnelle.

+ +
+
Assertions
+
Une assertion caractérisant la façon dont la correspondance peut se produire (en recherchant un motif avant, après ou avec une expression conditionnelle).
+
Limites
+
Permet d'indiquer le début ou la fin d'une ligne ou d'un mot.
+
Classes de caractère
+
Les classes permettent de distinguer différents caractères selon différents groupes (par exemple les lettres et les chiffres).
+
Groupes et intervalles
+
Permet d'indiquer un groupe ou un intervalle de caractères.
+
Quantificateurs
+
Permet d'indiquer un nombre de caractères ou d'expressions qui doivent correspondre.
+
Propriétés Unicode
+
Permet de distinguer les caractères en fonction de leurs caractéristiques Unicode (majuscule/minuscule, symbole mathématique, ponctuation).
+
+ +

Échapper des caractères

+ +

SI on souhaite rechercher certains caractères dans une chaîne de caractères et que ceux-ci ont une signification spéciale lorsqu'ils font partie d'une expression rationnelle (ex. "*"), il faudra échapper ces caractères spéciaux en plaçant une barre oblique inversée (backslash "\") devant. Ainsi, si on souhaite trouver un "a" suivi d'un astérisque ("*") suivi d'un "b", on pourra composer l'expression rationnelle : /a\*b/ où la barre oblique inversée échappe l'astérisque afin de lui enlever sa signification particulière.

+ +

De même si on écrit un littéral d'expression rationnelle et qu'on souhaite rechercher une barre oblique ("/") dans la chaîne cible, on pourra échapper ce caractère (sinon, il aura sa signification particulière aux expressions rationnelles et indiquera la fin du motif). Si on cherche la présence de "/exemple/" dans une chaîne de caractères, on pourra utiliser le littéral /\/exemple\//.

+ +

Il en va de même avec la barre oblique inversée (dont la signification spécifique est justement l'échappement) : si on veut rechercher la chaîne "C:\", on pourra utiliser le motif /C:\\/ (la première barre oblique inversée sert à échapper la seconde).

+ +

Lorsqu'on utilise le constructeur {{jsxref("RegExp")}} avec une chaîne de caractères en paramètre (plutôt qu'un littéral), il faudra échapper la barre oblique inversée qui a un sens particulier dans les chaînes de caractères. Ainsi, le littéral /a\*b/ et new RegExp("a\\*b") créeront la même expression (qui permet de chercher la lettre "a", suivie d'un astérisque, suivi de la lettre "b").

+ +

La tableau qui suit fournit une liste complète des caractères spéciaux pouvant être utilisés dans les expressions régulières ainsi que leur signification.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Caractères spéciaux utilisables pour les expressions rationnelles.
CaractèreSignification
\ +

Correspond selon les règles suivantes :
+
+ Une barre oblique inversée (backslash) précédant un caractère non spécial indique que le caractère qui suit est spécial et qu'il ne doit pas être interprété directement. Ainsi, un 'b', sans \ avant, correspondra pour les 'b' minuscules quel que soit leur position. En revanche '\b' ne correspondra à aucun caractère mais indique un caractère de fin de mot.
+
+ Un backslash précédant un caractère spécial indique que le caractère qui suit doit être interprété littéralement (et non pas comme un caractère spécial). Ainsi, le motif /a*/ utilise le caractère spécial '*' pour correspondre à 0 ou plusieurs 'a'. Le motif /a\*/, au contraire, rend '*' non-spécial pour correspondre aux chaînes de caractères qui comportent la lettre a et une astérisque, comme 'a*'.
+
+ Il ne faut pas oublier d'échapper le caractère \ car lui-même est un caractère d'échappement dans les chaînes de caractères. Cela est utile lorsqu'on utilise la notation RegExp("motif").

+
^Correspond au début la séquence. Si le marqueur (flag) de lignes multiples vaut true, il correspondra également immédiatement après un caractère de saut de ligne.
+
+ Ainsi, /^A/ ne correspond pas au 'A' de "un A", mais correspond au 'A' de "Arceau".
+
+ Le caractère '^' possède un sens différent lorsqu'il est utilisé dans un motif d'ensemble de caractères. Voir les compléments sur les ensembles de caractères pour plus de détails et d'exemples.
$ +

Correspond à la fin de la séquence. Si le marqueur (flag) de lignes multiples vaut true, il correspondra également immédiatement avant un caractère de saut de ligne.

+ +

Ainsi, /t$/ ne correspond pas au 't' de "printemps", mais correspond au 't' de "aliment".

+
* +

Correspond à l'expression précédente qui est répétée 0 ou plusieurs fois. Équivalent à {0,}

+ +

Ainsi, /bo*/ correspond à 'boo' dans "Un booléen" et à 'b' dans "Un bateau bleu", mais ne correspond à rien dans "Ce matin".

+
+ +

Correspond à l'expression précédente qui est répétée une ou plusieurs fois. C'est équivalent à {1,}.

+ +

Ainsi, /a+/ correspond au 'a' dans "maison" et à tous les 'a' dans "maaaaaaison" mais ne correspond à rien dans "mission".

+
?Correspond à l'expression précédente qui est présente une fois ou pas du tout. C'est équivalent à {0,1}.
+
+ Ainsi, /e?le?/ correspond au 'el' dans "gel" et au 'le' dans "angle" mais aussi au 'l' dans "Oslo".
+
+ S'il est utilisé immédiatement après l'un des quantificateurs : *, +, ?, ou {}, il rend le quantificateur moins « gourmand » auquel cas le moins de caractères correspond (le comportement par défaut, « gourmand », permettant de faire correspondre le plus de caractères possible). Par exemple /\d+/ utilisée avec "123abc" fait correspondre "123". Utiliser /\d+?/ à la même chaîne de caractères fait correspondre "1".
+
+ Ce symbole est également utilisé dans les tests de présence autour de l'expression, décrits par les lignes x(?=y) et x(?!y) de ce tableau.
. +

Par défaut, (Le point) correspond à n'importe quel caractère excepté un caractère de saut de ligne.

+ +

Ainsi, /.n/ correspond à 'un' et 'en' dans "Un baobab nain en cours de croissance" mais pas à 'nain'.

+ +

Si le marqueur s (dotAll) est utilisé, le point correspondra également aux caractères de saut de ligne.

+
(x) +

Correspond à 'x' et garde la correspondance en mémoire. Les parenthèses permettent de capturer l'expression dans un « groupe ».
+
+ Les '(toto)' et '(truc)', dans le motif /(toto) (truc) \1 \2/ correspondent et gardent en mémoire les deux premiers mots de la chaîne de caractère "toto truc toto truc". Les \1 et \2 du motif correspondent respectivement à la première et à la deuxième correspondances pour les sous-chaînes entre parenthèses. Lorsqu'on souhaite effectuer un remplacement, on utilisera $1 et $2 pour faire référence au premier et second groupe et $n pour faire référence au n-ième groupe capturé (ex. ('toto truc'.replace(/(...) (...)/, '$2 $1'). $& fera référence à la chaîne entière).

+
(?:x)Correspond à 'x' mais ne garde pas la correspondance en mémoire. Les parenthèses ne capturent pas l'expression et permettent d'utiliser des sous-expressions d'une expression régulière pour travailler plus finement. L'expression /(?:zoo){1,2}/ sans parenthèses non-capturantes les caractères {1,2} ne s'appliqueraient qu'au dernier 'o' de 'zoo'. Avec les parenthèses capturantes, {1,2} s'applique au mot entier 'zoo'. Pour plus d'informations, voir Utiliser les parenthèses ci-après.
x(?=y) +

Correspond à 'x' seulement s'il est suivi de 'y'. On appelle cela un test de succession (lookahead).

+ +

Ainsi, /Jack(?=Sparrow)/ correspond à 'Jack' seulement s'il est suivi de 'Sparrow'. /Jack(?=Sparrow|Bauer)/ correspond à 'Jack' seulement s'il est suivi de 'Sparrow' ou de 'Bauer'. Cependant, ni 'Sparrow' ni 'Bauer' ne feront partie de la correspondance.

+
x(?!y) +

Correspond à 'x' seulement si 'x' n'est pas suivi de 'y'.

+ +

Ainsi, /\d+(?!\.)/ correspond à un nombre qui n'est pas suivi par un point, cette expression utilisée avec la chaîne 3.141 correspondra pour '141' mais pas pour '3.141'.

+
(?<=y)x +

Correspond à x seulement si x est précédé par y. C'est ce qu'on appelle une recherche arrière (lookbehind).

+ +

Ainsi /(?<=Jack)Sprat/ correspond à "Sprat" seulement s'il est précédé de "Jack".
+ /(?<=Jack|Tom)Sprat/ correspond à "Sprat" seulement s'il est précédé de "Jack" ou "Tom".
+ Toutefois, "Jack" et "Tom" ne feront pas partie de la correspondance.

+
(?<!y)x +

Correspond à x uniquement si x n'est pas précédé par y (parfois appelée en anglais negated lookbehind).

+ +

Ainsi, /(?<!-)\d+/ correspondra à un nombre seulement si celui-ci n'est pas précédé d'un signe moins.
+ /(?<!-)\d+/.exec('3') cible "3".
+ /(?<!-)\d+/.exec('-3') ne trouve aucune correspondance car le nombre est précédé d'un signe.

+
x|y +

Correspond à 'x' ou 'y'.

+ +

Ainsi, /vert|rouge/ correspond à 'vert' dans "feu vert" et à 'rouge' dans "feu rouge".

+
{n}Correspond pour exactement n occurences de l'expression précédente. N doit être un entier positif.
+
+ Ainsi, /a{2}/ ne correspond pas au 'a' de "Mozilla" mais correspond à tous les 'a' de "Mozilaa" et aux deux premiers 'a' de "Mozillaaa".
{n,} +

Correspond lorsqu'il y a au moins n occurences de l'expression précédente. n doit être un entier positif.

+ +

Par exemple /a{2,}/ correspondra à "aa" ou à "aaa" ou encore à "aaaa" mais pas à "a".

+
{n,m} +

Lorsque n et m sont des entiers positifs, cela correspond à au moins n occurences de l'expression précédente et à au plus m occurrences. Lorsque m n'est pas utilisé, la valeur par défaut correspondante sera l'infini.

+ +

Ainsi, /a{1,3}/ ne correspond à rien dans "Mozill", au 'a' de "Mozilla", au deux premiers 'a' de "Mozillaa" et au trois premiers 'a' de "Mozillaaaaa". Pour ce dernier exemple, on doit noter que le correspondance ne se fait que sur "aaa" bien qu'il y ait plus de 'a' dans la chaîne de caractères.

+
[xyz]Un ensemble de caractère. Ce type de motif correspond pour n'importe quel caractètre présent entre les crochets, y compris les séquences d'échappement. Les caractères spéciaux comme le point (.) et l'astérisque ne sont pas considérés comme spéciaux au sein d'un ensemble et n'ont donc pas besoin d'être échappés. Il est possible de donner un ensemble sur un intervalle de caractères en utilisant un tiret (-), comme le montre l'exemple qui suit.
+
+ Le motif [a-d], aura les mêmes correspondances que [abcd], correspondant au 'b' de "bulle" et au 'c' de "ciel". Les motifis /[a-z.]+/ et /[\w.]+/ correspondront pour la chaîne entirère : "Adre.ss.e".
[^xyz] +

Exclusion d'un ensemble de caractères. Cela correspond à tout ce qui n'est pas compris entre crochets. Il est possible de fournir un intervalle de caractères en utilisant un tiret (-). Les autres règles qui s'appliquent pour l'ensemble de caractères (ci-avant) s'appliquent également ici.

+ +

Par exemple, [^abc] est équivalent à [^a-c]. Ils correspondent à 'u' dans "bulle" et à 'i' dans "ciel".

+
[\b]Correspond pour un retour arrière (U+0008). (À ne pas confondre avec \b.)
\b +

Correspond à la position d'uneAfter the limite de mot. Une limite de mot correspond à la position où un caractère d'un mot n'est pas suivi ou précédé d'un autre caractère de mot. Il faut savoir que la limite correspondante n'est pas incluse dans le résultat. Autrement dit, la longueur d'une telle correspondance est nulle. (À ne pas confondre avec [\b].)

+ +

Exemples :
+ /\bm/ correspond au 'm' dans "mignon" ;
+ /no\b/ ne correspond pas au 'no' de "mignon" car 'no' est suivi de 'n' qui n'est pas un caractère de limite de mot;
+ /non\b/ correspond au 'non' de "mignon" car 'non' représente la fin de la chaîne de caractère et n'est donc pas suivi par un caractère de mot.
+ /\w\b\w/ ne correspondra jamais à quoi que ce soit car un caractère de mot ne peut pas être suivi à la fois par un caractère de mot et un caractère n'étant pas un caractère de mot.

+ +
+

Note : Le moteur d'expressions rationnelles JavaScript définit un ensemble de caractères spécifiques qui doivent être considérés comme des caractères de mot. Tout caractère qui n'est pas dans cet ensemble est considéré comme une limite de mot. Cet ensemble de caractères est relativement limité car constitué uniquement des caractères de l'alphabet romain en minuscules et en majuscules, des chiffres décimaux et du tiret-bas (underscore). Les autres caractères, comme les caractères accentués (é ou ü par exemple), sont donc considérés comme des limites de mots.

+
+
\B +

Correspond à une "non-limite de mot". Cela correspond pour les cas suivants :

+ +
    +
  • Avant le premier caractère d'une chaîne de caractères
  • +
  • Après le dernier caractère d'une chaîne de caractères
  • +
  • Entre deux caractères de mot
  • +
  • Entre deux caractères qui ne sont pas des caractères de mot
  • +
  • Avec la chaîne vide.
  • +
+ +

Ainsi, /\B../ correspond au 'oo' de "football" (et /e\B./ correspond au 'er' dans "une mer "

+
\cX +

Étant donné un caractère X compris entre A et Z, cela correspond au caractère de contrôle dans une chaîne de caractères.

+ +

Ainsi, /\cM/ correspond au caractère de contrôle M (U+000D) d'une chaîne de caractère.

+
\d +

Correspond à un chiffre et est équivalent à [0-9].

+ +

Ainsi, /\d/ ou /[0-9]/ correspond à '2' dans "H2O est la molécule de l'eau".

+
\D +

Correspond à tout caractère qui n'est pas un chiffre et est équivalent à [^0-9].

+ +

Ainsi, /\D/ ou /[^0-9]/ correspond à 'H' dans "H2O est la molécule de l'eau".

+
\fCorrespond à un saut de page (U+000C).
\nCorrespond à un saut de ligne (U+000A).
\rCorrespond à un retour chariot (U+000D).
\s +

Correspond à un blanc (cela comprend les espace, tabulation, saut de ligne ou saut de page). C'est équivalent à [ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff].

+ +

Ainsi, /\s\w*/ correspond à ' toto' dans "truc toto".

+
\S +

Correspond à un caractère qui n'est pas un blanc. C'est équivalent à [^ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff].

+ +

Ainsi, /\S\w*/ correspond à 'truc' dans "truc toto".

+
\tCorrespond à une tabulation (U+0009).
\vCorrespond à une tabulation verticale (U+000B).
\w +

Correspond à n'importe quel caractère alphanumérique, y compris le tiret bas. C'est équivalent à [A-Za-z0-9_].

+ +

Ainsi, /\w/ correspond à 'l' dans "licorne", à '5' dans "5,28€", et à '3' dans "3D."

+
\W +

Correspond à n'importe quel caractère n'étant pas un caractère de mot. Cela est équivalent à [^A-Za-z0-9_].

+ +

Ainsi, /\W/ ou /[^A-Za-z0-9_]/ correspond à '%' dans "50%."

+
\n +

Soit n un entier strictement positif, cela fait référence au groupe de la n-ième expression entre parenthèses (en comptant les parenthèses ouvrantes).

+ +

Ainsi, /pomme(,)\spoire\1/ correspond à 'pomme, poire,' dans "pomme, poire, cerise, pêche".

+
\0Correspond au caractère NULL (U+0000). Il ne doit pas être suivi d'un autre chiffre car \0<chiffres> est une séquence d'échappement pour les nombres en notation octale (si besoin d'utiliser un chiffre ensuite, on pourra utiliser la forme \x00, cf. ci-après).
\xhhCorrespond au caractère dont le code hexadécimal est hh (deux chiffres hexadécimaux).
\uhhhhCorrespond au caractère dont le code est hhhh (quatre chiffres hexadécimaux).
\u{hhhh}(Uniquement actif quand le marqueur u est activé) Correspond au caractère dont la valeur Unicode est hhhh (en chiffre hexadécimaux).
+ +

Afin d'échapper les informations saisies par l'utilisateur et de traîter les chaînes de caractères pour les utiliser au sein d'un expression régulière correspondante, il est possible d'utiliser le remplacement suivant :

+ +
function escapeRegExp(string){
+  // $& correspond à la chaîne correspondante
+  // dans son intégralité
+  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+}
+ +

Le marqueur g situé en fin d'expression permet d'effectuer une recherche globale, qui parcoure toute la chaîne et renvoie l'ensemble des correspondances trouvées (voir Utiliser les marqueurs ci-après).

+ +
+

Note : Voir la page sur la méthode String.replace pour plus d'informations.

+
+ +

Utiliser les parenthèses

+ +

Les parenthèses encadrant une partie du motif de l'expression régulière peuvent être utilisées pour garder en mémoire les correspondances. Cela pourra être utile pour réutiliser la correspondance trouvée.

+ +

Ainsi, le motif /Chapitre (\d+)\.\d*/ utilise des caractères échappés et spéciaux et indique une partie du motif à garder en mémoire. Ce motif correspond aux caractères 'Chapitre ' suivi par un ou plusieurs caractères numériques (\d correspond à un chiffre et + indiquant que une série de 1 ou plusieurs chiffres), suivis par un point (qu'il est nécessaire d'échapper car c'est un caractère spécial, on utilise donc '\' pour indiquer qu'on souhaite reconnaître le caractère '.'), suivi par 0 ou plusieurs chiffres (\d correspondant à un chiffre et l'astérisque indiquant que le caractère est présent 0 ou plusieurs fois). Les parenthèses sont utilisées pour garder en mémoire les premiers chiffres correspondant.

+ +

Ce motif est trouvé dans "Ouvrir le Chapitre 4.3 au paragraphe 6" et le chiffre '4' est gardé en mémoire. Le motif n'est pas trouvé dans  "Chapitre 3 et 4", car la chaîne de caractères ne comporte pas de point après le '3'.

+ +

Pour qu'une partie de la chaîne de caractère corresponde mais que la correspondance ne soit pas gardée en mémoire, on pourra utiliser ?:. Ainsi, (?:\d+) correspondra pour une séquence de chiffres (1 ou plusieurs chiffres) mais on ne gardera pas en mémoire les caractères correspondants.

+ +

Utiliser les expressions rationnelles

+ +

Les expresssions régulières sont utilisées avec les méthodes test et exec de l'objet RegExp et avec les méthodes match, replace, search, et split de l'objet String. Ces méthodes sont expliquées en détail dans la Référence JavaScript.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Méthodes utilisant les expressions régulières
MéthodeDescription
{{jsxref("RegExp.exec", "exec")}}Une méthode de l'objet RegExp qui exécute une recherche de correspondance dans une chaîne de caractères. Elle renvoie un tableau d'informations ou null lorsqu'il n'y a pas de correspondance.
{{jsxref("RegExp.test", "test")}}Une méthode de l'objet RegExp testant la présence d'une correspondance dans une chaîne de caractères. Elle renvoie true ou false.
{{jsxref("String.match", "match")}}Une méthode de l'objet String qui exécute une recherche de correspondance dans une chaîne de caractères. Elle renvoie un tableau d'informations ou null lorsqu'il n'y a pas de correspondance.
{{jsxref("String.matchAll", "matchAll")}}Une méthode de l'objet String qui renvoie un itérateur contenant l'ensemble des correspondances, y compris les groupes capturants.
{{jsxref("String.search", "search")}}Une méthode de l'objet String qui teste la présence d'une correspondance dans une chaîne de correspondance. Elle renvoie la position de la correspondance ou -1 s'il n'y en a pas.
{{jsxref("String.replace", "replace")}}Une méthode de l'objet String qui recherche une correspondance dans une chaîne de caractères et qui remplace la correspondance par une chaîne de substitution.
{{jsxref("String.split", "split")}}Une méthode de l'objet String qui utilise une expression régulière ou une chaîne de caractères pour découper une chaîne de caractères en un tableau comprenant les fragments résultants.
+ +

Pour savoir si un motif est présent au sein d'une chaîne de caractères, utiliser les méthodes test ou search. Pour obtenir plus d'informations (moins rapidement) on utilisera les méthodes exec ou match. Si on utilise exec ou match et qu'une correspondance est trouvée, ces méthodes renverront un tableau et mettront à jour des propriétés de l'objet global RegExp et aussi de l'instance de RegExp associée à l'expression rationnelle. Si aucune correspondance n'est trouvée, la méthode exec renverra null (qui est automatiquement converti à false lors d'un test conditionnel).

+ +

Dans l'exemple qui suit, le script utilise la méthode exec pour trouver une correspondance dans une chaîne de caractères.

+ +
var monExpressionReguliere = /d(b+)d/g;
+var monTableau = monExpressionReguliere.exec("cdbbdbsbz");
+
+ +

S'il n'est pas nécessaire d'accéder aux propriétés de l'expression régulière, une autre façon de récupérer monTableau peut être :

+ +
var monTableau = /d(b+)d/g.exec("cdbbdbsbz");
+// équivalent à "cdbbdbsbz".match(/d(b+)d/g);
+
+ +

Si on souhaite construire une expression régulière à partir d'une chaîne de caractères, on peut utiliser le script suivant :

+ +
var monExpressionReguliere = new RegExp("d(b+)d", "g");
+var monTableau = monExpressionReguliere.exec("cdbbdbsbz");
+
+ +

Avec ces scripts, on obtient bien une correspondance, la méthode renvoie un tableau et met à jour les propriétés listées dans le tableau qui suit.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Résultats dûs à l'exécution d'une expression rationnelle.
ObjetPropriété ou indiceDescriptionPour cet exemple
monTableauLa chaîne de caractères correspondante et les fragments de chaînes gardés en mémoire.["dbbd", "bb"]
indexL'indice (débute à partir de 0) de la correspondance, compté dans la chaîne de caractère initiale.1
inputLa chaîne de caractères initiale."cdbbdbsbz"
[0]Les derniers caractères qui correspondent."dbbd"
monExpressionRégulièrelastIndexL'indice auquel débuter la prochaine correspondance. (Cette propriété n'est utilisée que si l'expression régulière utilise l'option g, décrite dans « Effectuer des recherches avancées avec les marqueurs ».5
sourceLe texte du motif, mis à jour à la création de l'expression régulière mais pas lors de son exécution."d(b+)d"
+ +

Comme le montre la seconde formulation de cet exemple, il est possible d'utiliser une expression rationnelle, créée avec un objet initialisé sans l'affecter à une variable. Cela implique qu'à chaque utilisation, on aura une nouvelle expression régulière distincte et qu'on ne pourra pas, pour cette raison, accéder aux propriétés de l'expression régulière. Avec le script suivant :

+ +
var monExpressionReguliere = /d(b+)d/g;
+var monTableau = monExpressionReguliere.exec("cdbbdbsbz");
+console.log("La valeur de lastIndex est " + monExpressionReguliere.lastIndex);
+
+// "La valeur de lastIndex est 5"
+
+ +

Si le script utilisé est :

+ +
var monTableau = /d(b+)d/g.exec("cdbbdbsbz");
+console.log("La valeur de lastIndex est " + /d(b+)d/g.lastIndex);
+
+// "La valeur de lastIndex est 0"
+
+ +

Les occurences de /d(b+)d/g dans les deux instructions sont des objets différents. Leurs propriétés lastIndex respectives ont donc des valeurs différentes. Quand il est nécessaire d'accéder aux propriétés d'un objet décrivant une expression rationnelle, il faudra d'abord l'affecter à une variable.

+ +

Utiliser les correspondances de groupes avec les parenthèses

+ +

Les parenthèses, utilisées dans un motif d'expression régulière, permettent de garder en mémoire un groupe (ou fragment) d'une correspondance. Ainsi, /a(b)c/ correspond aux caractères 'abc' et garde 'b' en mémoire. Pour récupérer ces fragments mémorisés, on peut utiliser les éléments du tableau array [1], ..., [n].

+ +

Le nombre de fragments qu'il est possible de garder entre parenthèses n'est pas limité. Le tableau renvoyé contiendra tout ce qui aura été trouvé. Les exemples qui suivent montrent comment utiliser cette syntaxe.

+ +

Le script qui suit utilise la méthode {{jsxref("String.replace", "replace()")}} pour échanger les mots d'une chaîne de caractères. Pour remplacer le texte, le script utilise $1 et $2 qui correspondent au premier et deuxième groupe correspondant.

+ +
var re = /(\w+)\s(\w+)/;
+var str = "Titi toto";
+var newstr = str.replace(re, "$2, $1");
+console.log(newstr);
+
+ +

Cela affichera "toto, Titi".

+ +

Effectuer des recherches avancées en utilisant les marqueurs (flags)

+ +

Les expressions rationnelles peuvent être utilisées avec des marqueurs optionnels permettant des recherches globales et/ou ne respectant pas la casse. Ces marqueurs peuvent être utilisés séparement ou ensemble, quel que soit l'ordre. Ils font partie de l'expression régulière.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Drapeaux utilisés avec les expressions régulières.
Drapeau (Flag)Description
gRecherche globale
iRecherche ne respectant pas la casse
mRecherche sur plusieurs lignes
sLe point peut correspondre aux caractères de saut de ligne.
uUnicode. Le motif de recherche est interprété comme une séquence de codets Unicode.
yEffectue une recherche qui « adhère », en partant de la position courante de la chaîne de caractères sur laquelle la recherche est effectuée. Voir la page sur {{jsxref("RegExp.sticky","sticky")}}.
+ +

Pour utiliser un marqueur avec une expression régulière, on utilisera la syntaxe suivante :

+ +
var re = /motif/marqueurs;
+
+ +

ou

+ +
var re = new RegExp("motif", "marqueurs");
+
+ +

Les marqueurs font partie intégrante d'une expression régulière, ils ne peuvent pas être ajoutés ou supprimés ensuite.

+ +

Ainsi, re = /\w+\s/g permet de créer une expression régulière pour trouver un ou plusieurs caractères suivis d'un espace, la recherche est effectuée globalement, sur toute la chaîne de caractères.

+ +
var re = /\w+\s/g;
+var str = "un deux trois quatre";
+var monTableau = str.match(re);
+console.log(monTableau);
+
+ +

Cela affichera ["un ", "deux ", "trois "]. On pourrait remplacer la ligne :

+ +
var re = /\w+\s/g;
+
+ +

avec la ligne :

+ +
var re = new RegExp("\\w+\\s", "g");
+
+ +

pour obtenir le même résultat.

+ +

Le comportement du marqueur 'g' est différent selon qu'il est utilisé avec exec() ou avec match(). Pour match(), c'est la chaîne de caractères qui invoque la méthode et l'expression rationnelle est alors un argument. Pour exec(), c'est l'expression rationnelle qui invoque la méthode et c'est la chaîne de caractères qui est passée en argument. Dans l'appel à exec(), le marqueur 'g' permet d'avoir une progression itérative.

+ +

Le marqueur m pourra être utilisé pour traiter une chaîne de caractères de plusieurs lignes comme plusieurs lignes distinctes. Si ce marqueur est utilisé, les caractères spéciaux ^ et $ correspondront au début ou à la fin de n'importe quelle ligne appartenant à la chaîne de caractères au lieu de correspondre simplement au début ou à la fin de la chaîne.

+ +

Exemples

+ +

Les exemples qui suivent utilisent les expressions régulières dans différents cas.

+ +

Changer l'ordre d'une saisie

+ +

L'exemple qui suit utilise les expressions régulières et string.split() et string.replace(). Le script nettoie la chaîne de caractères saisie qui contient des noms (prénom puis nom) séparés par des blancs, tabulations et points-virgules. Enfin il inverse les noms et prénoms puis trie la liste.

+ +
// La chaîne des noms contient plusieurs blancs et tabulations,
+// il peut y avoir plusieurs espaces entre le nom et le prénom.
+var noms = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ";
+
+var output = ["---------- Chaîne originale\n", noms + "\n"];
+
+// Préparer deux expressions régulières pour stocker un tableau.
+// et découper les chaînes dans ce tableau.
+
+// motif: on peut avoir des blancs, un point virgule puis d'autres blancs
+var motif = /\s*;\s*/;
+
+// Découper la chaîne de caractères en morceaux séparés par le précédent motif
+// Stocker ces morceaux dans un tableau listeNoms
+var listeNoms = noms.split(motif);
+
+// nouveau motif : un ou plusieurs caractères, des blancs puis des caractères.
+// On utilise des parenthèses pour garder en mémoire les groupes du motif.
+// On utilisera ces groupes par la suite.
+motif = /(\w+)\s+(\w+)/;
+
+// Nouveau tableau pour enregistrer les noms traités.
+var listeParNomFamille = [];
+
+// Afficher le tableau des noms et remplir le nouveau tableau
+// avec les noms et prénoms séparés par des virgules, le nom
+// de famille étant écrit en premier
+//
+// La méthode replace supprime tout ce qui correspond au motif
+// et le remplace par le nom (mémorisé), une virgule, un espace
+// et le prénom (mémorisé).
+//
+// Les variables $1 et $2 font références aux fragments gardés
+// en mémoire lors de l'utilisation du motif.
+
+output.push("---------- Après découpage avec l'expression régulière");
+
+var i, len;
+for (i = 0, len = listeNoms.length; i < len; i++){
+  output.push(listeNoms[i]);
+  listeParNomFamille[i] = listeNoms[i].replace(motif, "$2, $1");
+}
+
+// Afficher le nouveau tableau
+output.push("---------- Noms et prénoms inversés");
+for (i = 0, len = listeParNomFamille.length; i < len; i++){
+  output.push(listeParNomFamille[i]);
+}
+
+// Trier par le nom de famille puis afficher le tableau trié
+listeParNomFamille.sort();
+output.push("---------- Triée");
+for (i = 0, len = listeParNomFamille.length; i < len; i++){
+  output.push(listeParNomFamille[i]);
+}
+
+output.push("---------- Fin");
+
+console.log(output.join("\n"));
+
+ +

Utiliser les caractères spéciaux pour vérifier la saisie

+ +

Dans l'exemple suivant, on s'attend à ce que l'utilisateur saisissent un numéro de téléphone. Quand l'utilisateur appuie sur le bouton "Vérifier", le script vérifie la validité du numéro. Si le numéro est valide (il correspond à la séquence de caractères fournie par l'expression régulière), le script affiche un message remerciant l'utilisateur et confirmant le numéro. S'il est invalide, le script informe l'utilisateur et lui signifie que les informations saisies ne sont pas valides.

+ +

Dans les parenthèses sans mémoire (?: , l'expression régulière cherche les deux premiers chiffres ou l'indicatif du pays suivi d'un blanc et du premier chiffre, ce qui correspond à

+ +
\d{2}|\+\d{2}[ ]\d
+ +

Cette partie signifie : deux chiffres OU un signe '+' suivi de deux chiffres, un blanc et un autre chiffre.

+ +

Ensuite, on a un groupe qui est mémorisé (entre parenthèses) :

+ +
([- ])
+ +

Ce groupe correspond à ce qui va être utilisé pour séparer les différentes composantes du numéro de téléphone.

+ +

Ensuite,

+ +
\d{2}\1
+ +

signifie qu'on a deux chiffres suivi du premier groupe qui est celui qui définit le séparateur. Le reste est composé de la même façon. Ainsi les numéros de téléphone +33 1 23 45 67 89 et 01 23 45 67 89 seront tous les deux valides.

+ +

L'événement Change, provoqué quand l'utilisateur appuie sur Entrée, renseigne la valeur RegExp.input.

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+    <meta http-equiv="Content-Script-Type" content="text/javascript">
+    <script type="text/javascript">
+      var re = /(?:\d{2}|\+\d{2}[ ]\d)([- ])\d{2}\1\d{2}\1\d{2}\1\d{2}/;
+      function testInfo(phoneInput){
+        var OK = re.exec(phoneInput.value);
+        if (!OK)
+          window.alert(phone.input + " n'est pas un numéro de téléphone valide!");
+        else
+          window.alert("Merci, votre numéro est : " + OK[0]);
+      }
+    </script>
+  </head>
+  <body>
+    <p>Saisissez votre numéro de téléphone (avec indicatif) puis cliquez sur "Vérifier".
+        <br>Le format attendu est ## ## ## ## ## ou +## # ## ## ## ##.</p>
+    <form action="#">
+      <input id="phone"><button onclick="testInfo(document.getElementById('phone'));">Vérifier</button>
+    </form>
+  </body>
+</html>
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Formatage_du_texte", "Web/JavaScript/Guide/Collections_indexées")}}

diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/limites/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/limites/index.html" new file mode 100644 index 0000000000..513b3ae810 --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/limites/index.html" @@ -0,0 +1,95 @@ +--- +title: Limites +slug: Web/JavaScript/Guide/Expressions_régulières/Limites +tags: + - Guide + - JavaScript + - Limites + - RegExp +translation_of: Web/JavaScript/Guide/Regular_Expressions/Assertions +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

Les limites permettent d'indiquer les débuts et fins des lignes et des mots.

+ +

Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CaractèresSignification
^ +

Correspond au début la séquence. Si le marqueur (flag) de lignes multiples vaut true, il correspondra également immédiatement après un caractère de saut de ligne.
+
+ Ainsi, /^A/ ne correspond pas au 'A' de "un A", mais correspond au 'A' de "Arceau".
+
+ Le caractère '^' possède un sens différent lorsqu'il est utilisé dans un motif d'ensemble de caractères. Voir les compléments sur les ensembles de caractères pour plus de détails et d'exemples.

+
$ +

Correspond à la fin de la séquence. Si le marqueur (flag) de lignes multiples vaut true, il correspondra également immédiatement avant un caractère de saut de ligne.

+ +

Ainsi, /t$/ ne correspond pas au 't' de "printemps", mais correspond au 't' de "aliment".

+
\b +

Correspond à la position d'uneAfter the  limite de mot. Une limite de mot correspond à la position où un caractère d'un mot n'est pas suivi ou précédé d'un autre caractère de mot. Il faut savoir que la limite correspondante n'est pas incluse dans le résultat. Autrement dit, la longueur d'une telle correspondance est nulle. (À ne pas confondre avec [\b].)

+ +

Exemples :
+ /\bm/ correspond au 'm' dans "mignon" ;
+ /no\b/ ne correspond pas au  'no' de "mignon" car 'no' est suivi de 'n' qui n'est pas un caractère de limite de mot;
+ /non\b/ correspond au 'non' de "mignon" car 'non' représente la fin de la chaîne de caractère et n'est donc pas suivi par un caractère de mot.
+ /\w\b\w/ ne correspondra jamais à quoi que ce soit car un caractère de mot ne peut pas être suivi à la fois par un caractère de mot et un caractère n'étant pas un caractère de mot.

+ +
+

Note : Le moteur d'expressions rationnelles JavaScript définit un ensemble de caractères spécifiques qui doivent être considérés comme des caractères de mot. Tout caractère qui n'est pas dans cet ensemble est considéré comme une limite de mot. Cet ensemble de caractères est relativement limité car constitué uniquement des caractères de l'alphabet romain en minuscules et en majuscules, des chiffres décimaux et du tiret-bas (underscore). Les autres caractères, comme les caractères accentués (é ou ü par exemple), sont donc considérés comme des limites de mots.

+
+
\B +

Correspond à une "non-limite de mot". Cela correspond pour les cas suivants :

+ +
    +
  • Avant le premier caractère d'une chaîne de caractères
  • +
  • Après le dernier caractère d'une chaîne de caractères
  • +
  • Entre deux caractères de mot
  • +
  • Entre deux caractères qui ne sont pas des caractères de mot
  • +
  • Avec la chaîne vide.
  • +
+ +

Ainsi, /\B../ correspond au 'oo' de "football" (et /e\B./ correspond au 'er' dans "une mer "

+
+ +

Exemples

+ +

Cibler le début d'un champ grâce au caractère de contrôle ^

+ +

On utilisera le caractère spécial ^ afin de cibler le début d'un mot. Dans cet exemple, on filtre les fruits qui commencent par A grâce à l'expression rationnelle /^A/.

+ +
let fruits = ["Ananas", "Melon", "Orange", "Abricot", "Pomme"];
+
+let fruitsDebutantParA = fruits.filter(fruit => /^A/.test(fruit));
+console.table(fruitsDebutantsParA); // [ 'Ananas', 'Abricot' ]
+ +

Dans ce deuxième exemple, on utilise ^ à la fois pour indiquer le début du mot et pour indiquer un groupe complémentaire pour ne sélectionner que les fruits dont le nom ne commence pas par A.

+ +
let fruits = ["Ananas", "Melon", "Orange", "Abricot", "Pomme"];
+
+let fruitsNeDebutantPasParA = fruits.filter(fruit => /^[^A]/.test(fruit));
+console.table(fruitsNeDebutantPasParA); // [ 'Melon', 'Orange', 'Pomme' ]]
+
diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/quantificateurs/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/quantificateurs/index.html" new file mode 100644 index 0000000000..75137ff14d --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/quantificateurs/index.html" @@ -0,0 +1,97 @@ +--- +title: Quantificateurs +slug: Web/JavaScript/Guide/Expressions_régulières/Quantificateurs +tags: + - Guide + - JavaScript + - Quantificateurs + - RegExp +translation_of: Web/JavaScript/Guide/Regular_Expressions/Quantifiers +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

Les quantificateurs indiquent le nombre de caractères ou d'expressions qu'il faut pour une correspondance.

+ +

Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CaractèresSignification
x* +

Correspond à l'expression précédente qui est répétée 0 ou plusieurs fois. Équivalent à {0,}

+ +

Ainsi, /bo*/ correspond à 'boo' dans "Un booléen" et à 'b' dans "Un bateau bleu", mais ne correspond à rien dans "Ce matin".

+
x+ +

Correspond à l'expression précédente qui est répétée une ou plusieurs fois. C'est équivalent à {1,}.

+ +

Ainsi, /a+/ correspond au 'a' dans "maison" et à tous les 'a' dans "maaaaaaison" mais ne correspond à rien dans "mission".

+
x? +

Correspond à l'expression précédente qui est présente une fois ou pas du tout. C'est équivalent à {0,1}.
+
+ Ainsi, /e?le?/ correspond au 'el' dans "gel" et au 'le' dans "angle" mais aussi au 'l' dans "Oslo".
+
+ S'il est utilisé immédiatement après l'un des quantificateurs : *, +, ?, ou {}, il rend le quantificateur moins « gourmand » auquel cas le moins de caractères correspond (le comportement par défaut, « gourmand », permettant de faire correspondre le plus de caractères possible). Par exemple /\d+/ utilisée avec "123abc" fait correspondre "123". Utiliser /\d+?/ à la même chaîne de caractères fait correspondre "1".
+
+ Ce symbole est également utilisé dans les tests de présence autour de l'expression, décrits par les lignes x(?=y) et x(?!y) de ce tableau.

+
x{n} +

Correspond pour exactement n occurences de l'expression précédente. N doit être un entier positif.
+
+ Ainsi, /a{2}/ ne correspond pas au 'a' de "Mozilla" mais correspond à tous les 'a' de "Mozilaa" et aux deux premiers 'a' de "Mozillaaa".

+
x{n,} +

Correspond lorsqu'il y a au moins n occurences de l'expression précédente. n doit être un entier positif.

+ +

Par exemple /a{2,}/ correspondra à "aa" ou à "aaa" ou encore à "aaaa" mais pas à "a".

+
x{n,m} +

Lorsque n et m sont des entiers positifs, cela correspond à au moins n occurences de l'expression précédente et à au plus m occurrences. Lorsque m n'est pas utilisé, la valeur par défaut correspondante sera l'infini.

+ +

Ainsi, /a{1,3}/ ne correspond à rien dans "Mozill", au 'a' de "Mozilla", au deux premiers 'a' de "Mozillaa" et au trois premiers 'a' de "Mozillaaaaa". Pour ce dernier exemple, on doit noter que le correspondance ne se fait que sur "aaa" bien qu'il y ait plus de 'a' dans la chaîne de caractères.

+
+

x*?
+ x+?
+ x??
+ x{n}?
+ x{n,}?
+ x{n,m}?

+
+

Correspond à l'expression précédente qui est présente une fois ou pas du tout. C'est équivalent à {0,1}.
+
+ Ainsi, /e?le?/ correspond au 'el' dans "gel" et au 'le' dans "angle" mais aussi au 'l' dans "Oslo".
+
+ S'il est utilisé immédiatement après l'un des quantificateurs : *, +, ?, ou {}, il rend le quantificateur moins « gourmand » auquel cas le moins de caractères correspond (le comportement par défaut, « gourmand », permettant de faire correspondre le plus de caractères possible). Par exemple /\d+/ utilisée avec "123abc" fait correspondre "123". Utiliser /\d+?/ à la même chaîne de caractères fait correspondre "1".
+
+ Ce symbole est également utilisé dans les tests de présence autour de l'expression, décrits par les lignes x(?=y) et x(?!y) de ce tableau.

+
diff --git "a/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/\303\251chappement_propri\303\251t\303\251s_unicode/index.html" "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/\303\251chappement_propri\303\251t\303\251s_unicode/index.html" new file mode 100644 index 0000000000..df05a95dda --- /dev/null +++ "b/files/fr/web/javascript/guide/expressions_r\303\251guli\303\250res/\303\251chappement_propri\303\251t\303\251s_unicode/index.html" @@ -0,0 +1,430 @@ +--- +title: Échappement des propriétés Unicode +slug: Web/JavaScript/Guide/Expressions_régulières/Échappement_propriétés_Unicode +tags: + - Expressions rationnelles + - Expressions régulières + - Guide + - JavaScript + - regex +translation_of: Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

Les séquences d'échappement pour les propriétés Unicode permettent de distinguer les caractères Unicodes en fonction de leurs propriétés : majuscules, minuscules, symboles mathématiques, ponctuation, etc.

+ +

Syntaxe

+ +
// Valeurs non-binaires
+\p{UnicodePropertyName=ValeurPropriétéUnicode}
+\p{UnicodePropertyName}
+
+// Valeurs binaires et non-binaires
+\p{UnicodePropertyName}
+
+ +
+
ValeurPropriétéUnicode
+
Une des valeurs listées ci-après. Pour certaines valeurs, le mot-clé NomPropriétéUnicode et le signe égal peuvent être omis.
+
+ +

Valeurs

+ +

Non-binaires

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ÉchappementsSignification
\p{LC}
+ \p{Cased_Letter}
+ \p{UnicodePropertyName=Cased_Letter}
N'importe quelle lettre avec la version minuscule et la version majuscule. Équivalent à \p{Lu}|\p{Ll}|p{Lt}.
\p{Close_Punctuation}
+ \p{UnicodePropertyName=Close_Punctuation}
\p{Connector_Punctuation}
+ \p{UnicodePropertyName=Connector_Punctuation}
\p{Control}
+ \p{UnicodePropertyName=Control}
\p{Currency_Symbol}
+ \p{UnicodePropertyName=Currency_Symbol}
\p{Dash_Punctuation}
+ \p{UnicodePropertyName=Dash_Punctuation}
\p{Decimal_Number}
+ \p{UnicodePropertyName=Decimal_Number}
\p{Enclosing_Mark}
+ \p{UnicodePropertyName=Enclosing_Mark}
\p{Final_Punctuation}
+ ​​​​​​​\p{UnicodePropertyName=Final_Punctuation}
\p{Format}
+ ​​​​​​​\p{UnicodePropertyName=Format}
\p{Initial_Punctuation}
+ ​​​​​​​\p{UnicodePropertyName=Initial_Punctuation}
\p{Letter}
+ ​​​​​​​\p{UnicodePropertyName=Letter}
\p{Letter_Number}
+ ​​​​​​​\p{UnicodePropertyName=Line_Separator}
\p{Lowercase_Letter}
+ ​​​​​​​\p{UnicodePropertyName=Lowercase_Letter}
\p{Mark}
+ ​​​​​​​\p{UnicodePropertyName=Mark}
\p{Math_Symbol;}
+ ​​​​​​​\p{UnicodePropertyName=Math_Symbol}
\p{Modifier_Letter}
+ ​​​​​​​\p{UnicodePropertyName=Modifier_Letter}
\p{Modifier_Symbol}
+ ​​​​​​​\p{UnicodePropertyName=Modifier_Symbol}
\p{Nonspacing_Mark}
+ ​​​​​​​\p{UnicodePropertyName=Nonspacing_Mark}
\p{Number}
+ ​​​​​​​\p{UnicodePropertyName=Number}
\p{Open_Punctuation}
+ ​​​​​​​\p{UnicodePropertyName=Open_Punctuation}
\p{Other}
+ ​​​​​​​\p{UnicodePropertyName=Other_Letter}
\p{Other_Letter}
+ ​​​​​​​\p{UnicodePropertyName=Other_Letter}
\p{Other_Number}
+ ​​​​​​​\p{UnicodePropertyName=Other_Number}
\p{Other_Punctuation}
+ ​​​​​​​\p{UnicodePropertyName=Other_Punctuation}
\p{Paragraph_Separator}
+ ​​​​​​​\p{UnicodePropertyName=Paragraph_Separator}
\p{Private_Use}Meaning
+ ​​​​​​​\p{UnicodePropertyName=Private_Use}
\p{Punctuation}
+ ​​​​​​​\p{UnicodePropertyName=Punctuation}
\p{Separator}
+ ​​​​​​​\p{UnicodePropertyName=Separator}
\p{Space_Separator}
+ ​​​​​​​\p{UnicodePropertyName=Space_Separator}
\p{Spaceing_Mark}
+ ​​​​​​​\p{UnicodePropertyName=Spacing_Mark}
\p{Surrogate}
+ ​​​​​​​\p{UnicodePropertyName=Surrogate}
\p{Symbol}
+ ​​​​​​​\p{UnicodePropertyName=Symbol}
\p{Titlecase_Letter}
+ ​​​​​​​\p{UnicodePropertyName=Titlecase_Letter}
\p{Unassigned}
+ ​​​​​​​\p{UnicodePropertyName=Unassigned}
\p{Uppercase_Letter}
+ ​​​​​​​\p{UnicodePropertyName=UppercaseLetter}
+ +

Binaires

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ÉchappementSignification
\p{Alphabetic}
\p{Bidi_Control}
\p{Bidi_Mirrored}
\p{Case_Ignorable}
\p{Cased}
\p{Changes_When_Casefolded}
\p{Changes_When_Casemapped}
\p{Changes_When_Lowercased}
\p{Changes_When_NFKC_Casefolded}
\p{Changes_When_Titlecased}
\p{Changes_When_Uppercased}
\p{Dash}
\p{Default_Ignorable_Code_Point}
\p{Deprecated}
\p{Diacritic}
\p{Emoji}
\p{Emoji_Component}
\p{Emoji_Modifier}
\p{Emoji_Modifier_Base}
\p{Emoji_Presentation}
\p{Extender}
\p{Grapheme_Base}
\p{Grapheme_Extend}
\p{Hex_Digit}
\p{ID_Continue}
\p{ID_Start}
\p{Ideographic}
\p{IDS_Binary_Operator}
\p{IDS_Trinary_Operator}
\p{Join_Control}
\p{Logical_Order_Exception}
\p{Lowercase}
\p{Math}
\p{Noncharacter_Code_Point}
\p{Pattern_Syntax}
\p{Pattern_White_Space}
\p{Quotation_Mark}
\p{Radical}
\p{RegionalIndicator}
\p{Sentence_Terminal}
\p{Soft_Dotted}
\p{Terminal_Punctuation}
\p{Unified_Ideograph}
\p{Uppercase}
\p{Variation_Selector}
\p{White_Space}
\p{XID_Continue}
\p{XID_Start}
diff --git a/files/fr/web/javascript/guide/fonctions/index.html b/files/fr/web/javascript/guide/fonctions/index.html new file mode 100644 index 0000000000..68c87566ff --- /dev/null +++ b/files/fr/web/javascript/guide/fonctions/index.html @@ -0,0 +1,670 @@ +--- +title: Fonctions +slug: Web/JavaScript/Guide/Fonctions +tags: + - Débutant + - Functions + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Functions +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Boucles_et_it%C3%A9ration", "Web/JavaScript/Guide/Expressions_et_Op%C3%A9rateurs")}}

+ +

Les fonctions font partie des briques fondamentales de JavaScript. Une fonction est une procédure JavaScript, un ensemble d'instructions effectuant une tâche ou calculant une valeur. Afin d'utiliser une fonction, il est nécessaire de l'avoir auparavant définie au sein de la portée dans laquelle on souhaite l'appeler.

+ +

On pourra également lire le chapitre de la référence JavaScript sur les fonctions pour étudier plus en détails ce concept

+ +

Définir des fonctions

+ +

Les déclarations de fonctions

+ +

Une définition de fonction (aussi appelée déclaration de fonction ou instruction de fonction) est construite avec le mot-clé function, suivi par :

+ + + +

Le code suivant, par exemple, définit une fonction intitulée carré :

+ +
function carré(nombre) {
+  return nombre * nombre;
+}
+
+ +

La fonction carré prend un seul argument, appelé nombre. La fonction est composée d'une seule instruction qui renvoie l'argument de la fonction (nombre) multiplié par lui-même. L'instruction return spécifie la valeur qui est renvoyée par la fonction.

+ +
return nombre * nombre;
+
+ +

Les paramètres primitifs (comme les nombres) sont passés à la fonction par valeur. La valeur est passée à la fonction mais si cette dernière change la valeur du paramètre, cela n'aura pas d'impact au niveau global ou au niveau de ce qui a appelé la fonction.

+ +

Si l'argument passé à la fonction est un objet (une valeur non-primitive, comme un objet {{jsxref("Array")}} ou un objet défini par l'utilisateur), et que la fonction change les propriétés de cet objet, ces changements seront visibles en dehors de la fonction. Par exemple :

+ +
function maFonction(monObjet) {
+  monObjet.fabricant = "Toyota";
+}
+
+var mavoiture = {fabricant: "Honda", modèle: "Accord", année: 1998};
+var x, y;
+
+x = mavoiture.fabricant;     // x aura la valeur "Honda"
+
+maFonction(mavoiture);
+y = mavoiture.fabricant; // y aura la valeur "Toyota"
+                         // (la propriété fabricant a été modifiée par la fonction)
+
+ +
+

Note : Affecter un nouvel objet au paramètre n'aura pas d'effet en dehors de la fonction car cela revient à changer la valeur du paramètre plutôt que la valeur d'une des propriétés de l'objet. Par exemple :

+
+ +
function maFonction(monObjet) {
+  monObjet = {fabricant: "Ford", modèle: "Focus", année: 2006};
+}
+
+var mavoiture = {fabricant: "Honda", modèle: "Accord", année: 1998};
+var x, y;
+
+x = mavoiture.fabricant;     // x reçoit la valeur "Honda"
+
+maFonction(mavoiture);
+y = mavoiture.fabricant;     // y reçoit la valeur "Honda"
+
+ +

Dans le premier exemple, l'objet mavoiture était passé à la fonction maFonction qui le modifiait. Dans le second exemple, la fonction n'a pas modifié l'objet qui avait été passé en argument, elle a créé une nouvelle variable locale, possédant le même nom que l'objet global passé en argument : il n'y a donc pas de modifications sur cet objet global.

+ +

Les expressions de fonction

+ +

Syntaxiquement, la déclaration de fonction utilisée ci-dessus est une instruction. On peut également créer une fonction grâce à une expression de fonction. De telles fonctions peuvent être anonymes (ne pas avoir de nom correspondant). La fonction carré aurait pu être définie de la façon suivante :

+ +
var carré = function (nombre) { return nombre * nombre };
+var x = carré(4); //x reçoit la valeur 16
+ +

Cependant, un nom peut être utilisé dans une expression de fonction, ce afin de l'utiliser dans la fonction (récursivité) ou afin de l'identifier dans les appels tracés par un éventuel débogueur :

+ +
var factorielle = function fac(n) { return n < 2 ? 1 : n * fac(n - 1) };
+
+console.log(factorielle(3));
+
+ +

Les expressions de fonction sont pratiques lorsqu'il s'agit de passer une fonction comme argument d'une autre fonction. Dans l'exemple qui suit, la fonction map est définie et appelée avec une fonction anonyme comme premier argument :

+ +
function map(f, a) {
+  var resultat = []; // Créer un nouveau tableau Array
+  for (var i = 0; i != a.length; i++)
+    resultat[i] = f(a[i]);
+  return resultat;
+}
+
+ +

Le code suivant applique la fonction cube sur chacun des éléments du tableau :

+ +
var cube = function(x) { return x * x * x}; // Une expression de fonction
+map(cube, [0, 1, 2, 5, 10]);
+
+ +

Le résultat de la dernière instruction est le tableau [0, 1, 8, 125, 1000].

+ +

En JavaScript, une fonction peut être définie selon une condition. Le fragment de code qui suit définit une fonction seulement si num vaut 0 :

+ +
var maFonction;
+if (num === 0){
+  maFonction = function(monObjet) {
+    monObjet.fabricant = "Toyota"
+  }
+}
+ +

Une autre façon de définir des fonctions est d'utiliser le constructeur de l'objet {{jsxref("Function")}} afin de créer des fonctions à partir d'une chaîne lors de l'exécution, de la même façon que {{jsxref("Objets_globaux/eval", "eval()")}}.

+ +

Une méthode est une fonction étant une propriété d'un objet. Vous trouverez plus de détails sur ces éléments dans le chapitre suivant du guide : Utiliser les objets.

+ +

Appeler des fonctions

+ +

La seule définition d'une fonction ne permet pas d'exécuter la fonction. Cela permet de lui donner un nom et de définir ce qui doit être fait lorsque la fonction est appelée. Appeler la fonction permet d'effectuer les actions des instructions avec les paramètres indiqués. Par exemple, si on définit la fonction carré, on peut l'appeler de la façon suivante :

+ +
carré(5);
+
+ +

Cette instruction appellera la fonction avec un argument valant 5. La fonction exécute ses instructions et renvoie la valeur 25.

+ +

Les fonctions doivent appartenir à la portée dans laquelle elles sont appelées. En revanche, la déclaration d'une fonction peut être faite après l'appel :

+ +
console.log(carré(5));
+/* ... */
+function carré(n) { return n*n }
+
+ +

La portée d'une fonction est la fonction dans laquelle elle est déclarée ou le programme entier si elle est déclarée au niveau le plus haut.

+ +
+

Note : Cela ne fonctionne que si la définition de la fonction utilise la syntaxe précédente (function nomFonction(){}). Le code ci-dessous ne fonctionnera pas :

+
+ +
console.log(carré); // La fonction carré est remontée/hoisted mais vaut undefined
+console.log(carré(5)); // TypeError: carré is not a function
+var carré = function (n) {
+  return n * n;
+}
+
+// Et avec let...
+
+console.log(carré2); // ReferenceError: carré2 is not defined
+console.log(carré2(5)); // TypeError: carré2 is not a function
+
+let carré2 = function (n) {
+  return n * n;
+}
+
+ +

Les arguments d'une fonction ne sont pas limités aux chaînes de caractères et aux nombres. Il est possible de passer des objets. La fonction show_props (définie dans le chapitre sur l'utilisation des objets) est un exemple de fonction utilisant un argument qui est un objet.

+ +

Une fonction peut être récursive, c'est-à-dire qu'elle peut s'appeler elle-même. Voici la fonction qui calcule récursivement la factorielle d'un nombre :

+ +
function factorielle(n){
+  if ((n === 0) || (n === 1))
+    return 1;
+  else
+    return (n * factorielle(n - 1));
+}
+
+ +

On peut ensuite calculer les factorielles des nombres 1 à 5 :

+ +
var a, b, c, d, e;
+a = factorielle(1); // a reçoit la valeur 1
+b = factorielle(2); // b reçoit la valeur 2
+c = factorielle(3); // c reçoit la valeur 6
+d = factorielle(4); // d reçoit la valeur 24
+e = factorielle(5); // e reçoit la valeur 120
+
+ +

Il existe d'autres façons d'appeler des fonctions. Il existe souvent des cas où une fonction doit être appelée dynamiquement, où le nombre d'arguments peut varier, où le contexte de l'appel d'une fonction doit être créé en fonction d'un objet déterminé lors de l'exécution. Les fonctions sont des objets, en tant que tels, elles possèdent des méthodes (voir la page sur l'objet {{jsxref("Function")}}). L'une d'entre elles, {{jsxref("Function.apply","apply()")}} peut être utilisée pour réaliser le dernier cas de figure (exécution d'une fonction avec un objet déterminé à l'exécution).

+ +

Portée d'une fonction

+ +

On ne peut pas accéder aux variables définies dans une fonction en dehors de cette fonction : ces variables n'existent que dans la portée de la fonction. En revanche, une fonction peut accéder aux différentes variables et fonctions qui appartiennent à la portée dans laquelle elle est définie. Une fonction définie dans une autre fonction peut également accéder à toutes les variables de la fonction « parente » et à toute autre variable accessible depuis la fonction « parente ».

+ +
// Les variables suivantes sont globales
+var num1 = 20,
+    num2 = 3,
+    nom = "Licorne";
+
+// Cette fonction est définie dans la portée globale
+function multiplier() {
+  return num1 * num2;
+}
+
+multiplier(); // Renvoie 60
+
+// Un exemple de fonction imbriquée
+function getScore () {
+  var num1 = 2,
+      num2 = 3;
+
+  function ajoute() {
+    return nom + " a marqué " + (num1 + num2);
+  }
+
+  return ajoute();
+}
+
+getScore(); // Renvoie "Licorne a marqué 5"
+
+ +

Portée et pile de fonctions

+ +

La récursivité

+ +

Une fonction peut faire référence à elle-même et s'appeler elle-même. Il existe trois moyens pour qu'une fonction fasse référence à elle-même :

+ +
    +
  1. Le nom de la fonction
  2. +
  3. arguments.callee
  4. +
  5. Une variable de la portée qui fait référence à la fonction
  6. +
+ +

Par exemple, avec la définition de fonction suivante :

+ +
var toto = function truc() {
+   // les instructions de la fonction
+};
+ +

Dans le corps de la fonction, ces trois éléments seront équivalents :

+ +
    +
  1. truc()
  2. +
  3. arguments.callee()
  4. +
  5. toto()
  6. +
+ +

Une fonction qui s'appelle elle-même est appelée une fonction récursive. Sous certains aspects, une récursion est semblable à une boucle : toutes les deux exécutent le même code plusieurs fois et toutes les deux requièrent une condition d'arrêt (pour éviter une boucle ou une récursion infinie). Par exemple, ce fragment de code utilisant une boucle :

+ +
var x = 0;
+while (x < 10) { // "x < 10" représente la condition d'arrêt
+  // faire quelque chose
+  x++;
+}
+ +

pourra être converti en une fonction récursive de la façon suivante :

+ +
function boucle(x) {
+  if (x >= 10) // "x >= 10" représente la condition d'arrêt (équivalent à "!(x < 10)")
+    return;
+  // faire quelque chose
+  boucle(x + 1); // l'appel récursif
+}
+boucle(0);
+ +

Malgré cela, certains algorithmes ne peuvent pas être convertis en boucles itératives. Ainsi, récupérer l'ensemble des nœuds d'un arbre (le DOM par exemple) se fait plus simplement en utilisant la récursivité :

+ +
function parcourirArbre(noeud) {
+  if (noeud === null) //
+    return;
+  // faire quelque chose avec le noeud
+  for (var i = 0; i < noeud.childNodes.length; i++) {
+    parcourirArbre(noeud.childNodes[i]);
+  }
+}
+ +

Contrairement à l'exemple précédent avec la fonction boucle, ici, chaque appel récursif entraîne lui-même plusieurs appels (et non un seul).

+ +

Théoriquement, il est possible de convertir tout algorithme récursif en un algorithme non récursif (avec des boucles par exemple). Généralement, la logique obtenue est plus complexe et nécessite l'utilisation d'une pile. La récursivité utilise également une pile, la pile de fonction.

+ +

Ce type de « comportement » peut-être observé avec l'exemple suivant :

+ +
function toto(i) {
+  if (i < 0)
+    return;
+  console.log('début : ' + i);
+  toto(i - 1);
+  console.log('fin : ' + i);
+}
+toto(3);
+ +

qui affichera :

+ +
début : 3
+début : 2
+début : 1
+début : 0
+fin : 0
+fin : 1
+fin : 2
+fin : 3
+ +

Fonctions imbriquées et fermetures

+ +

Il est possible d'imbriquer une fonction dans une autre fonction. La portée de la fonction fille (celle qui est imbriquée) n'est pas contenue dans la portée de la fonction parente. En revanche, la fonction fille bénéficie bien des informations de la fonction parente grâce à sa portée. On a ce qu'on appelle une fermeture (closure en anglais). Une fermeture est une expression (généralement une fonction) qui accède à des variables libres ainsi qu'à un environnement qui lie ces variables (ce qui « ferme » l'expression).

+ +

Une fonction imbriquée étant une fermeture, cela signifie qu'une fonction imbriquée peut en quelque sorte hériter des arguments et des variables de la fonction parente.

+ +

En résumé :

+ + + + + +
+

Note : Sur les fermetures, voir également l'article à ce sujet.

+
+ +

L'exemple qui suit illustre l'imbrication de fonctions :

+ +
function ajouteCarrés(a, b) {
+  function carré(x) {
+    return x * x;
+  }
+  return carré(a) + carré(b);
+}
+a = ajouteCarrés(2,3); // renvoie 13
+b = ajouteCarrés(3,4); // renvoie 25
+c = ajouteCarrés(4,5); // renvoie 41
+ +

La fonction interne étant une fermeture, on peut appeler la fonction parente afin de définir les arguments pour la fonction englobante et ceux de la fonction fille :

+ +
function parente(x) {
+  function fille(y) {
+    return x + y;
+  }
+  return fille;
+}
+fn_fille = parente(3); // Fournit une fonction qui ajoute 3 à ce qu'on lui donnera
+résultat = fn_fille(5); // renvoie 8
+
+résultat1 = parente(3)(5); // renvoie 8
+ +

Préservation des variables

+ +

Dans l'exemple précédent, x a été « préservé » lorsque la fonction fille a été renvoyée. Une fermeture conserve les arguments et les variables de chaque portée qu'elle référence. Chaque appel à la fonction parente pouvant fournir un contexte différents selon les arguments, cela entraînera la création d'une nouvelle fermeture. La mémoire associée ne pourra être libérée que lorsque la fonction fille ne sera plus accessible.

+ +

Ce mode de fonctionnement n'est pas différent de celui des références vers les objets. Cependant, il est souvent plus compliqué à détecter car les références ne sont pas définies explicitement dans le code et car il n'est pas possible de les inspecter.

+ +

Imbriquer plusieurs fonctions

+ +

Il est possible d'imbriquer des fonctions sur plus de deux niveaux, par exemple, on peut avoir une fonction A qui contient une fonction B qui contient une fonction C. Les fonctions B et C sont des fermetures et B peut accéder à la portée de A, C peut accéder à la portée de B. Ainsi, C accède à la portée de B qui lui accède à la portée de A, C accède donc à la portée de A (transitivité). Les fermetures peuvent donc contenir plusieurs portées, c'est ce qu'on appelle le chaînage de portées.

+ +

Par exemple :

+ +
function A(x) {
+  function B(y) {
+    function C(z) {
+      console.log(x + y + z);
+    }
+    C(3);
+  }
+  B(2);
+}
+A(1); // affichera 6 (1 + 2 + 3)
+ +

Dans cet exemple C accède au y de B et au x de A. Ceci est rendu possible car :

+ +
    +
  1. B est une fermeture qui contient A, autrement dit B peut accéder aux arguments et aux variables de A.
  2. +
  3. C est une fermeture qui contient B.
  4. +
  5. La fermeture de B contient A donc la fermeture de C contient A, C peut ainsi accéder aux arguments et aux variables de B et A. On dit que C chaîne les portées de B et de A (dans cet ordre).
  6. +
+ +

La réciproque n'est pas vraie. A ne peut pas accéder à C, car A ne peut pas accéder aux arguments ou aux variables de B, or C est une variable de B. De cette façon, C reste privée en dehors de B.

+ +

Conflits de nommage

+ +

Lorsque deux arguments ou variables des portées d'une fermeture ont le même nom, il y a un conflit de noms. Dans ces cas, ce sera la portée la plus imbriquée qui prendra la priorité sur le nom, la portée la plus « externe » aura la priorité la plus faible pour les noms de variables. Du point de vue de la chaîne des portées, la première portée sur la chaîne est la portée la plus imbriquée et la dernière est la portée située le plus à l'extérieur :

+ +
function externe() {
+  var x = 10;
+  function interne(x) {
+    return x;
+  }
+  return interne;
+}
+résultat = externe()(20); // renvoie 20 et pas 10
+ +

Le conflit se produit à l'instruction return x entre le paramètre x de la fonction interne et la variable x de la fonction externe. La chaîne de portée est ici {interne, externe, objet global}. Ainsi, le paramètre x de interne a la priorité sur la variable x de la fonction externe, le résultat obtenu est donc 20 et non 10.

+ +

Fermetures (closures)

+ +

Les fermetures sont l'une des fonctionnalités les plus intéressantes de JavaScript. Comme on l'a vu précédemment, JavaScript permet d'imbriquer des fonctions et la fonction interne aura accès aux variables et paramètres de la fonction parente. À l'inverse, la fonction parente ne pourra pas accéder aux variables liées à la fonction interne. Cela fournit une certaine sécurité pour les variables de la fonction interne. De plus, si la fonction interne peut exister plus longtemps que la fonction parente, les variables et fonctions de la fonction parente pourront exister au travers de la fonction interne. On crée une fermeture lorsque la fonction interne est disponible en dehors de la fonction parente.

+ +
var animal = function(nom) {   // La fonction externe utilise un paramètre "nom"
+  var getNom = function () {
+    return nom;                // La fonction interne accède à la variable "nom" de la fonction externe
+  }
+  return getNom;               // Renvoie la fonction interne pour la rendre disponible en dehors de la portée de la fonction parente
+}
+
+monAnimal = animal("Licorne");
+
+monAnimal();                   // Renvoie "Licorne"
+ +

Bien entendu, dans la pratique, les cas peuvent être plus complexes. On peut renvoyer un objet qui contient des méthodes manipulant les variables internes de la fonction parente.

+ +
var créerAnimal  = function (nom) {
+  var sexe;
+
+  return {
+    setNom: function(nouveauNom) {
+      nom = nouveauNom;
+    },
+
+    getNom: function () {
+      return nom;
+    },
+
+    getSexe: function () {
+      return sexe;
+    },
+
+    setSexe: function(nouveauSexe) {
+      if (typeof nouveauSexe == "string" && (nouveauSexe.toLowerCase() == "mâle" || nouveauSexe.toLowerCase() == "femelle")) {
+        sexe = nouveauSexe;
+      }
+    }
+  }
+}
+
+var animal = créerAnimal("Licorne");
+animal.getNom();        // Licorne
+
+animal.setNom("Bobby");
+animal.setSexe("mâle");
+animal.getSexe();       // mâle
+animal.getNom();        // Bobby
+ +

Dans le code précédent, la variable nom est de la fonction externe est accessible depuis les fonctions internes. Il est impossible d'accéder aux variables internes en dehors des fonctions internes. Les variables internes agissent comme des coffres-forts pour les fonctions internes. Elles permettent d'avoir un accès persistent et encapsulé aux données internes. Pour les fonctions, il n'est pas nécessaire de les affecter à une variable ou même de les nommer.

+ +
var getCode = (function (){
+  var codeAPI = "0]Eal(eh&2";    // Un code qu'on ne souhaite pas diffuser ni modifier
+
+  return function () {
+    return codeAPI;
+  };
+})();
+
+getCode();    // Renvoie la valeur du code
+ +

Il y a malgré tout quelques pièges auxquels il faut faire attention lorsqu'on utilise les fermetures. Si une fonction imbriquée définit une variable avec le même nom que le nom d'une variable de la portée externe, il n'y aura plus aucun moyen d'accéder à la variable.

+ +
var créerAnimal = function(nom) {  // La fonction externe définit une variable appelée "nom"
+  return {
+    setNom: function(nom) {    // La fonction imbriquée définit une variable appelée "nom"
+      nom = nom;               // ??? comment accéder à la variable "nom" définie par la fonction externe
+    }
+  }
+}
+ +

L'opérateur this doit être traité avec précaution dans les fermetures. Attention, this fait référence au contexte où la fonction est appelée et non à l'endroit où il est défini.

+ +

Utiliser l'objet arguments

+ +

Les arguments d'une fonction sont maintenus dans un objet semblable à un tableau. Dans une fonction, il est possible d'utiliser les arguments passés à la fonction de la façon suivante :

+ +
arguments[i]
+ +

i représente l'index ordinal de l'argument (le premier argument ayant un indice à 0). On accède donc au premier argument avec arguments[0]. Le nombre total d'arguments est fourni grâce à arguments.length.

+ +

En utilisant l'objet arguments, il est possible de recenser les arguments supplémentaires fournis à la fonction si jamais il y a plus d'arguments fournis que requis. Cet objet est souvent utile si on ne connaît pas le nombre d'arguments passés à la fonction. La propriété arguments.length permet de déterminer le nombre d'arguments réellement passés à la fonction. On peut donc ensuite accéder aux différents arguments en parcourant l'objet arguments.

+ +

Par exemple, on peut construire une fonction qui concatène plusieurs chaînes. Le seul argument formellement défini sera la chaîne utilisée pour concaténer les différentes chaînes. On peut définir la fonction de la façon suivante :

+ +
function monConcat(séparateur) {
+   var result = ""; // on initialise la liste
+   var i;
+   // on parcourt les arguments
+   for (i = 1; i < arguments.length; i++) {
+      result += arguments[i] + séparateur;
+   }
+   return result;
+}
+ +

On peut passer autant d'arguments que nécessaire à cette fonction. Ils seront tous concaténés dans une chaîne finale. Ainsi, on aura :

+ +
// renverra "rouge, orange, bleu, "
+monConcat(", ", "red", "orange", "blue");
+
+// renverra "éléphant; girafe; lion; singe; "
+monConcat("; ", "éléphant", "girafe", "lion", "singe");
+
+// renverra "sauge. basilic. origan. poivre. échalotte. "
+monConcat(". ", "sauge", "basilic", "origan", "poivre", "échalotte");
+ +
+

Note : arguments est une variable « semblable » à un tableau. Mais ce n'est pas un tableau au sens strict. En effet, il possède un index numéroté ainsi qu'une propriété length. En revanche, il ne possède pas les méthodes classiques de manipulation des tableaux (Array).

+
+ +

Voir la page sur l'objet {{jsxref("Function")}} dans la référence JavaScript pour plus d'informations.

+ +

Paramètres des fonctions

+ +

À partir d'ECMAScript 2015, deux sortes de paramètres sont introduites : les paramètres par défaut et les paramètres du reste.

+ +

Les paramètres par défaut

+ +

En JavaScript, par défaut, les paramètres des fonctions vaudront undefined. Il peut toutefois être utile de définir une valeur par défaut différente. Les paramètres par défaut permettent de répondre à ce besoin.

+ +

Avant ECMAScript 2015, la stratégie pour manipuler des valeurs par défaut adaptées était de tester si la valeur du paramètre était indéfinie puis de lui affecter la valeur souhaitée si c'était le cas. Par exemple, dans le code qui suit, on ne fournit pas de valeur pour b dans l'appel, la valeur sera undefined lors de l'évaluation de a*b et l'appel à multiplier aurait renvoyé NaN. Pour éviter ça, la deuxième ligne définit une valeur par défaut au cas où b n'est pas renseigné :

+ +
function multiplier(a, b) {
+  b = typeof b !== 'undefined' ?  b : 1;
+
+  return a*b;
+}
+
+multiplier(5); // 5
+
+ +

Si on peut utiliser les paramètres par défaut, il n'est plus nécessaire de faire l'opération à l'intérieur du corps de la fonction, il suffit de déclarer que la valeur par défaut pour b est 1 dans la signature de la fonction :

+ +
function multiplier(a, b = 1) {
+  return a*b;
+}
+
+multiplier(5); // 5
+ +

Pour plus de détails, voir la page sur les paramètres par défaut dans la référence.

+ +

Les paramètres du reste

+ +

La syntaxe des paramètres du reste permet de représenter un nombre indéfini d'arguments contenus dans un tableau. Dans l'exemple suivant, on utilise les paramètres du reste pour collecter les arguments à partir du deuxième et jusqu'au dernier. Ces arguments sont multipliés par le premier. Dans cet exemple, on utilise une fonction fléchée, concept qui est présenté et illustré dans la section qui suit.

+ +
function multiplier(facteur, ...lesArgs) {
+  return lesArgs.map(x => facteur * x);
+}
+
+var arr = multiplier(2, 1, 2, 3);
+console.log(arr); // [2, 4, 6]
+ +

Fonctions fléchées

+ +

Une expression de fonction fléchée permet d'utiliser une syntaxe plus concise que les expressions de fonctions classiques. Une telle fonction ne possède alors pas de valeur propre pour thisargumentssuper ou new.target. Les fonctions fléchées sont nécessairement anonymes.

+ +

Les fonctions fléchées ont été introduites pour deux raisons principales : une syntaxe plus courte et l'absence de this rattaché à la fonction. Voir aussi ce billet sur tech.mozfr.org sur les fonctions fléchées.

+ +

 

+ +

 

+ +

Concision de la syntaxe

+ +

Dans certaines constructions fonctionnelles, on peut apprécier une syntaxe courte. Par exemple, si on compare les deux dernières lignes de ce fragment de code :

+ +
var a = [
+  "Hydrogen",
+  "Helium",
+  "Lithium",
+  "Beryl­lium"
+];
+
+var a2 = a.map(function(s){ return s.length });
+console.log(a2); // affiche [8, 6, 7, 9]
+var a3 = a.map( s => s.length );
+console.log(a3); // affiche [8, 6, 7, 9]
+ +

Pas de this distinct

+ +

Avant les fonctions fléchées, chaque nouvelle fonction définissait sa propre valeur this (un nouvel objet dans le cas d'un constructeur, undefined lors des appels en mode strict, l'objet courant dans le cas d'une méthode, etc.). Cela pouvait poser quelques problèmes avec un style de programmation orienté objet.

+ +
function Personne() {
+  // Le constructeur Personne() utilise `this` comme lui-même.
+  this.âge = 0;
+
+  setInterval(function grandir() {
+    // En mode non-strict, la fonction grandir() définit `this`
+    // avec l'objet global, qui est donc différent du `this`
+    // défini par le constructeur Person().
+    this.âge++;
+  }, 1000);
+}
+
+var p = new Personne();
+ +

Avec ECMAScript 3/5, ce problème fut résolu avec l'affectation de la valeur de this dans une variable a variable that could be closed over.

+ +
function Personne() {
+  var self = this; // Certains utilisent `that`, d'autres `self`.
+                   // On utilisera l'un des deux et on pas
+                   // l'autre pour être cohérent.
+  self.âge = 0;
+
+  setInterval(function grandir() {
+    // La fonction callback fait référence à la variable `self`
+    // qui est bien la valeur attendue liée à l'objet.
+    self.âge++;
+  }, 1000);
+}
+ +

On aurait aussi pu créer une fonction liée afin que la « bonne » valeur de this soit passée à la fonction grandir().

+ +

Les fonctions fléchées capturent la valeur de this dans le contexte englobant et cela permet de manipuler la valeur pertinente ici :

+ +
function Personne(){
+  this.âge = 0;
+
+  setInterval(() => {
+    this.âge++; // this fait référence à l'objet personne
+  }, 1000);
+}
+
+var p = new Personne();
+ +

Fonctions prédéfinies

+ +

JavaScript possède plusieurs fonctions natives, disponibles au plus haut niveau :

+ +
+
{{jsxref("Objets_globaux/eval","eval()")}}
+
+

La fonction eval() permet d'évaluer du code JavaScript contenu dans une chaîne de caractères.

+
+
{{jsxref("Objets_globaux/uneval","uneval()")}} {{non-standard_inline}}
+
+

La fonction uneval() crée une représentation sous la forme d'une chaîne de caractères pour le code source d'un objet.

+
+
{{jsxref("Objets_globaux/isFinite","isFinite()")}}
+
+

La fonction isFinite() détermine si la valeur passée est un nombre fini. Si nécessaire, le paramètre sera converti en un nombre.

+
+
{{jsxref("Objets_globaux/isNaN","isNaN()")}}
+
+

La fonction isNaN() détermine si une valeur est {{jsxref("NaN")}} ou non. Note : On pourra également utiliser {{jsxref("Number.isNaN()")}} défini avec ECMAScript 6 ou utiliser typeof afin de déterminer si la valeur est Not-A-Number.

+
+
{{jsxref("Objets_globaux/parseFloat","parseFloat()")}}
+
+

La fonction parseFloat() convertit une chaîne de caractères en un nombre flottant.

+
+
{{jsxref("Objets_globaux/parseInt","parseInt()")}}
+
+

La fonction parseInt() convertit une chaîne de caractères et renvoie un entier dans la base donnée.

+
+
{{jsxref("Objets_globaux/decodeURI","decodeURI()")}}
+
+

La fonction decodeURI() décode un Uniform Resource Identifier (URI) créé par {{jsxref("Objets_globaux/encodeURI","encodeURI()")}} ou une méthode similaire.

+
+
{{jsxref("Objets_globaux/decodeURIComponent","decodeURIComponent()")}}
+
+

La fonction decodeURIComponent() décode un composant d'un Uniform Resource Identifier (URI) créé par {{jsxref("Objets_globaux/encodeURIComponent","encodeURIComponent")}} ou une méthode similaire.

+
+
{{jsxref("Objets_globaux/encodeURI","encodeURI()")}}
+
+

La fonction encodeURI() encode un Uniform Resource Identifier (URI) en remplaçant chaque exemplaire de certains caractères par un, deux, trois voire quatre séquences d'échappement représentant l'encodage UTF-8 du caractères (quatre séquences seront utilisées uniquement lorsque le caractère est composé d'une paire de deux demi-codets).

+
+
{{jsxref("Objets_globaux/encodeURIComponent","encodeURIComponent()")}}
+
+

La fonction encodeURIComponent() encode un composant d'un Uniform Resource Identifier (URI) en remplaçant chaque exemplaire de certains caractères par un, deux, trois voire quatre séquences d'échappement représentant l'encodage UTF-8 du caractères (quatre séquences seront utilisées uniquement lorsque le caractère est composé d'une paire de deux demi-codets).

+
+
{{jsxref("Objets_globaux/escape","escape()")}} {{deprecated_inline}}
+
+

La fonction dépréciée escape() calcule une nouvelle chaîne de caractères pour laquelle certains caractères ont été remplacés par leur séquence d'échappement hexadécimale. Les fonctions {{jsxref("Objets_globaux/encodeURI","encodeURI()")}} ou {{jsxref("Objets_globaux/encodeURIComponent","encodeURIComponent()")}} doivent être utilisées à la place.

+
+
{{jsxref("Objets_globaux/unescape","unescape()")}} {{deprecated_inline}}
+
+

La fonction dépréciée unescape() calcule une nouvelle chaîne de caractères pour laquelle les séquences d'échappement hexadécimales sont remplacées par les caractères qu'elles représentent. Les séquences d'échappement introduites peuvent provenir d'une fonction telle que {{jsxref("Objets_globaux/escape","escape()")}}. unescape est dépréciée et doit être remplacée par {{jsxref("Objets_globaux/decodeURI","decodeURI()")}} ou {{jsxref("Objets_globaux/decodeURIComponent","decodeURIComponent()")}}.

+
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Boucles_et_it%C3%A9ration", "Web/JavaScript/Guide/Expressions_et_Op%C3%A9rateurs")}}

diff --git a/files/fr/web/javascript/guide/formatage_du_texte/index.html b/files/fr/web/javascript/guide/formatage_du_texte/index.html new file mode 100644 index 0000000000..32e270c8d7 --- /dev/null +++ b/files/fr/web/javascript/guide/formatage_du_texte/index.html @@ -0,0 +1,255 @@ +--- +title: Formatage de texte +slug: Web/JavaScript/Guide/Formatage_du_texte +tags: + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Text_formatting +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
+ +

Ce chapitre présente comment travailler avec les chaînes de caractères et le texte en JavaScript.

+ +

Les chaînes de caractères

+ +

Le type {{Glossary("String")}} de JavaScript est utilisé pour représenter des données textuelles. C'est un ensemble d'"éléments" de valeurs non signées sur 16 bits (unités de codage UTF-16). Chaque élément dans la chaîne de caractères occupe une position dans la chaîne de caractères. Le premier élément se trouve à l'indice 0, le suivant à l'indice 1 et ainsi de suite. La longueur d'une chaîne de caractères est le nombre d'éléments qu'elle contient. Vous pouvez créer des chaînes de caractères en utilisant des littéraux de chaîne de caractères ou des objets chaîne de caractères.

+ + + +

Les littéraux de chaînes de caractères

+ +

Vous pouvez créer des chaînes de caractères simple en utilisant des apostrophes simples ou doubles :

+ +
'machin'
+"truc"
+ +

Des chaînes plus avancées peuvent être créées en utilisant des séquences d'échappement.

+ +

Les séquences d'échappement hexadécimales

+ +

Le nombre situé après \x est interprété comme un nombre hexadécimal :

+ +
'\xA9' // "©"
+ +

Les séquences d'échappement Unicode

+ +

Les séquences d'échappement Unicode requièrent au moins quatres caractères hexadécimaux après \u.

+ +
'\u00A9' // "©"
+ +

L'échappement d'unités de codage Unicode

+ +

Nouveau dans ECMAScript 2015. Avec les échappements d'unités de codage Unicode, tout caractère peut être échappé en utilisant des nombres hexadécimaux, de sorte qu'il est possible de d'utiliser des unités de codage Unicode jusqu'à 0x10FFFF. Avec les échappements Unicode simples, il est souvent nécessaire d'écrire les moitiés de remplacement séparément pour obtenir le même résultat.

+ +

Voir aussi {{jsxref("String.fromCodePoint()")}} ou {{jsxref("String.prototype.codePointAt()")}}.

+ +
'\u{2F804}'
+
+// Le même avec des échappements Unicode simples
+'\uD87E\uDC04'
+
+ +

Les objets String

+ +

L'objet {{jsxref("String")}} est un conteneur autour du type de donnée primitif chaîne de caractères.

+ +
var s = new String('foo'); // crée un objet String
+console.log(s); // affiche : {'0': 'f', '1': 'o', '2': 'o'}
+typeof s; // retourne 'object'
+ +

Vous pouvez appeler chacune des méthodes de l'objet String avec une valeur littérale de chaîne de caractères : JavaScript convertira automatiquement le littéral en un objet String temporaire, appellera la méthode, puis supprimera l'objet String temporaire. Vous pouvez aussi utiliser la propriété String.length sur un littéral de chaîne de caractères.

+ +

Vous devriez utiliser des littéraux de chaîne de caractères, à moins que vous n'ayez spécifiquement besoin d'un objet String, parce que les objets String peuvent avoir un comportement contre-intuitif :

+ +
var s1 = '2 + 2'; // crée une valeur de chaîne de caractères
+var s2 = new String('2 + 2'); // crée un objet String
+eval(s1); // renvoie le nombre 4
+eval(s2); // renvoie la chaîne "2 + 2"
+ +

Un objet String possède une propriété, length, qui indique le nombre d'unités de codage UTF-16 dans la chaîne de caractères. Par exemple, le code suivant affecte à x la valeur 16, parce que la chaîne "Bonjour, Monde !" contient 16 caractères, chacun représenté par une unité de codage UTF-16. Vous pouvez accéder à chaque unité de codage en utilisant une syntaxe de tableau entre crochets. Vous ne pouvez pas changer les caractères, du fait que les chaînes sont des objets immuables (semblables à des tableaux) :

+ +
var machaine = 'Bonjour, Monde !';
+var x = machaine.length;
+machaine[0] = 'L'; // cela n'a aucun effet car les chaînes sont immuables
+machaine[0]; // cela renvoie "B"
+
+ +

Les caractères dont les valeurs scalaires sont supérieures à U+FFFF (comme certains rares caractères chinois/japonais/coréens/vietnamiens et certains emojis) sont stockés en UTF-16 via deux unités de codage de remplacement. Par exemple, une chaîne de caractères contenant le seul caractère U+1F600 ("Emoji grinning face") aura une longueur de 2. Le fait d'accéder aux unités de codage individuelles dans une telle chaîne de caractères en utilisant des crochets peut avoir des conséquences indésirables telles que la génération d'unité de codage de remplacement non conformes, en violation du standard Unicode. (Des exemples devraient être ajoutés à cette page après que le bug MDN 857438 sera corrigé. Voir aussi {{jsxref("String.fromCodePoint()")}} ou {{jsxref("String.prototype.codePointAt()")}}.

+ +

Un objet String a une grande variété de méthodes : par exemple, celles qui retournent une variation de la chaîne de caractères elle-même, telles que substring et toUpperCase.

+ +

Le tableau suivant résume les méthodes des objets {{jsxref("String")}}.

+ +

Méthodes de String

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MéthodeDescription
{{jsxref("String.charAt", "charAt")}}, {{jsxref("String.charCodeAt", "charCodeAt")}}, {{jsxref("String.codePointAt", "codePointAt")}}Retourne le caractère ou le code de caractère à la position spécifiée de la chaîne de caractères.
{{jsxref("String.indexOf", "indexOf")}}, {{jsxref("String.lastIndexOf", "lastIndexOf")}}Retourne la position de la sous-chaîne spécifiée dans la chaîne de caractères, ou la dernière position de la sous-chaîne spécifiée, respectivement.
{{jsxref("String.startsWith", "startsWith")}}, {{jsxref("String.endsWith", "endsWith")}}, {{jsxref("String.includes", "includes")}}Retourne le fait de savoir si la chaîne de caractères courante commence ou non par, finit ou non par, ou contient ou non, la chaîne spécifiée.
{{jsxref("String.concat", "concat")}}Combine le texte de deux chaînes de caractères et retourne une nouvelle chaîne de caractères.
{{jsxref("String.fromCharCode", "fromCharCode")}}, {{jsxref("String.fromCodePoint", "fromCodePoint")}},Construit une chaîne de caractères à partir de la séquence de valeurs Unicode fournie. Cette méthode est une méthode de la classe String et non une instance de String.
{{jsxref("String.split", "split")}}Découpe un objet String en un tableau de chaînes de caractères en découpant la chaîne de caractères en sous-chaînes.
{{jsxref("String.slice", "slice")}}Extrait une partie de la chaîne de caractères et retourne une nouvelle chaîne de caractères.
{{jsxref("String.substring", "substring")}}, {{jsxref("String.substr", "substr")}}Retourne le sous-ensemble spécifié de la chaîne de caractères, en spécifiant soit des indices de début et de fin, soit l'indice de début et une longueur.
{{jsxref("String.match", "match")}}, {{jsxref("String.matchAll", "matchAll")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.search", "search")}}Ces fonctions utilisent des expressions rationnelles.
{{jsxref("String.toLowerCase", "toLowerCase")}}, {{jsxref("String.toUpperCase", "toUpperCase")}} +

Retourne la chaîne tout en minuscules ou tout en majuscules, respectivement.

+
{{jsxref("String.normalize", "normalize")}}Retourne la Forme Normalisée Unicode de la chaîne de caractères appelante.
{{jsxref("String.repeat", "repeat")}}Retourne une chaîne constituée des éléments de l'objet répétés le nombre de fois donné.
{{jsxref("String.trim", "trim")}}Retire les blancs en début et en fin de chaîne.
+ +

Les littéraux de modèle multi-lignes

+ +

Le littéraux de modèle sont des littéraux de chaîne de caractères permettant des expressions intégrées. Avec eux, vous pouvez utiliser des chaînes de caractères multi-lignes et des fonctionnalités d'interpolation de chaînes.

+ +

Les littéraux de gabarits sont délimités par des accents graves (ou backticks` ` en anglais), au lieu des apostrophes simples ou doubles. Les littéraux de modèle peuvent contenir des marque-places. Ceux-ci sont indiqués par le signe dollar et des accolades (${expression}).

+ +

Multi-lignes

+ +

Tout caractère de passage à la ligne inséré dans le source fait partie du littéral de modèle. En utilisant les chaînes de caractères normales, vous auriez eu à utiliser la syntaxe suivante afin d'avoir des chaînes de caractères multi-lignes :

+ +
console.log('chaîne ligne de texte 1\n\
+chaîne ligne de texte 2');
+// "chaîne ligne de texte 1
+// chaîne ligne de texte 2"
+ +

Pour obtenir le même effet avec des chaînes de caractères multi-lignes, vous pouvez maintenant écrire :

+ +
console.log(`chaîne ligne de texte 1
+chaîne ligne de texte 2`);
+// "chaîne ligne de texte 1
+// chaîne ligne de texte 2"
+ +

Expressions intégrées

+ +

Pour intégrer des expressions dans des chaînes normales, vous devriez utiliser la syntaxe suivante :

+ +
var a = 5;
+var b = 10;
+console.log('Quinze vaut ' + (a + b) + ' et\npas ' + (2 * a + b) + '.');
+// "Quinze vaut 15 et
+// pas 20."
+ +

Maintenant, avec les modèles, vous pouvez utiliser du sucre syntaxique rendant plus lisibles les substitutions comme celle-ci :

+ +
var a = 5;
+var b = 10;
+console.log(`Quinze vaut ${a + b} et\npas ${2 * a + b}.`);
+// "Quinze vaut 15 et
+// pas 20."
+ +

Pour plus d'informations, voir les Littéraux de modèles dans la Référence JavaScript.

+ +

Internationalisation

+ +

L'objet {{jsxref("Intl")}} est l'espace de noms pour l'API d'Internationalisation de l'ECMAScript, qui fournit des fonctionnalités de comparaison de chaînes de caractères, de formatage de nombres, et de formatage des dates et heures prenant en compte la langue. Les constructeurs pour les objets {{jsxref("Collator")}}, {{jsxref("NumberFormat")}} et {{jsxref("DateTimeFormat")}} sont des propriétés de l'objet Intl.

+ +

Formatage date et heure

+ +

L'objet {{jsxref("DateTimeFormat")}} est utile pour formater la date et l'heure. Ce qui suit formate une date en anglais telle qu'utilisée aux États-Unis (le résultat sera différent dans une autre zone horaire).

+ +
var msParJour = 24 * 60 * 60 * 1000;
+
+// 17 juillet 2014 00:00:00 UTC.
+var _17juillet2014 = new Date(msParJour * (44 * 365 + 11 + 197));
+
+var options = { year: "2-digit", month: "2-digit", day: "2-digit",
+                hour: "2-digit", minute: "2-digit", timeZoneName: "short" };
+var dateHeureAmericaine = new Intl.DateTimeFormat("en-US", options).format;
+
+console.log(dateHeureAmericaine(_17juillet2014)); // 07/16/14, 5:00 PM PDT
+
+ +

Formatage des nombres

+ +

L'objet {{jsxref("NumberFormat")}} est utile pour formater les nombres, par exemple, les devises :

+ +
var prixDeLEssence = new Intl.NumberFormat("en-US",
+                        { style: "currency", currency: "USD",
+                          minimumFractionDigits: 3 });
+
+console.log(prixDeLEssence.format(5.259)); // $5.259
+
+var decimalesHanRMBEnChine = new Intl.NumberFormat("zh-CN-u-nu-hanidec",
+                        { style: "currency", currency: "CNY" });
+
+console.log(decimalesHanRMBEnChine.format(1314.25)); // ¥ 一,三一四.二五
+
+ +

Ordonnancement

+ +

L'objet {{jsxref("Collator")}} est utile pour comparer et trier des chaînes de caractères.

+ +

Par exemple, il y a en fait deux ordres de tri en allemand, annuaire et dictionnaire. Annuaire met l'accent sur le son, et c'est comme si "ä", "ö", etc. étaient étendus en "ae", "oe", etc. avant le tri :

+ +
var noms = ['Hochberg', 'Hönigswald', 'Holzman'];
+
+var annuaireAllemand = new Intl.Collator('de-DE-u-co-phonebk');
+
+// Comme si tri de ['Hochberg', 'Hoenigswald', 'Holzman']:
+console.log(noms.sort(annuaireAllemand.compare).join(', '));
+// Affiche "Hochberg, Hönigswald, Holzman"
+
+ +

Certains mots allemands se conjuguent avec des umlauts supplémentaires, de sorte que dans les dictionnaires, le fait d'ignorer les umlauts pour le tri  est perceptible (sauf lors du tri de mots ne différant que par des umlauts, comme schon avant schön).

+ +
var dictionnaireAllemand = new Intl.Collator('de-DE-u-co-dict');
+
+// Comme si tri de ["Hochberg", "Honigswald", "Holzman"]:
+console.log(nom.sort(dictionnaireAllemand.compare).join(', '));
+// Affiche "Hochberg, Holzman, Hönigswald"
+
+ +

Pour plus d'informations sur l'API {{jsxref("Intl")}}, voir aussi Introducing the JavaScript Internationalization API.

+ +

{{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}

diff --git a/files/fr/web/javascript/guide/index.html b/files/fr/web/javascript/guide/index.html new file mode 100644 index 0000000000..d91a8a85b8 --- /dev/null +++ b/files/fr/web/javascript/guide/index.html @@ -0,0 +1,136 @@ +--- +title: Guide JavaScript +slug: Web/JavaScript/Guide +tags: + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide +--- +
{{jsSidebar("JavaScript Guide")}}
+ +

Le guide JavaScript illustre comment utiliser JavaScript et fournit un aperçu des fonctionnalités du langage. Pour des informations exhaustives à propos des fonctionnalités du langage, voir la référence JavaScript.

+ +

Chapitres

+ +

Ce guide est divisé en plusieurs chapitres :

+ + + + + + + + + +

{{Next("Web/JavaScript/Guide/Introduction")}}

diff --git a/files/fr/web/javascript/guide/introduction/index.html b/files/fr/web/javascript/guide/introduction/index.html new file mode 100644 index 0000000000..ff45b841eb --- /dev/null +++ b/files/fr/web/javascript/guide/introduction/index.html @@ -0,0 +1,135 @@ +--- +title: Introduction +slug: Web/JavaScript/Guide/Introduction +tags: + - Débutant + - Guide + - Intro + - JavaScript +translation_of: Web/JavaScript/Guide/Introduction +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Types_et_grammaire")}}
+ +

Ce chapitre introduit JavaScript et présente certains de ses concepts fondamentaux.

+ +

Ce que vous devriez déjà savoir

+ +

Pour lire ce guide, il est conseillé d'avoir :

+ + + +

Où trouver des informations concernant JavaScript

+ +

La documentation MDN pour JavaScript comprend :

+ + + +

Si vous débutez en JavaScript, vous pouvez commencer par les articles de la section Apprendre et du Guide JavaScript. Une fois que vous maîtrisez les briques de bases, vous pourrez utiliser la référence JavaScript pour obtenir des informations détaillées sur chacun des objets natifs et des instructions.

+ +

Qu'est-ce que JavaScript ?

+ +

JavaScript est un langage de script, multi-plateforme et orienté objet. C'est un langage léger qui doit faire partie d'un environnement hôte (un navigateur web par exemple) pour qu'il puisse être utilisé sur les objets de cet environnement.

+ +

JavaScript contient une bibliothèque standard d'objets tels que Array, Date, et Math, ainsi qu'un ensemble d'éléments de langage tels que les opérateurs, les structures de contrôles et les instructions. Ces fonctionnalités centrales et natives de JavaScript peuvent être étendues de plusieurs façons en fournissant d'autres objets, par exemple :

+ + + +

JavaScript et Java

+ +

JavaScript et Java se ressemblent sur certains aspects mais ils sont fondamentalement différents l'un de l'autre. Le langage JavaScript ressemble à Java mais n'est pas typé statiquement et le typage de JavaScript est faible (alors qu'il est fort en Java). La syntaxe des expressions JavaScript est très proche de celle du Java avec les conventions de nommage et les constructions conditionnelles par exemple : c'est une des raisons qui a fait que le langage LiveScript a été renommé en JavaScript.

+ +

À la différence de Java qui est un système compilé et dont les classes sont déclarées, JavaScript est traité lors de l'exécution et possède quelques types de données pour représenter les nombres, les booléens et les chaînes de caractères (entre autres). JavaScript utilise un modèle basé sur les prototypes pour représenter les liens entre les objets alors que Java utilise un modèle plus courant basé sur les classes. Les prototypes permettent d'avoir un héritage dynamique. Ainsi, les caractéristiques héritées par un objet peuvent varier dans le temps. JavaScript supporte également les fonctions qui sont des objets à part entière et qui peuvent être des propriétés d'autres objets.

+ +

JavaScript est un langage plutôt « libre » comparé au Java. Il n'est pas nécessaire de déclarer toutes les variables, classes et méthodes. Il n'est pas nécessaire de savoir si une méthode est publique, privée ou protégée et il n'y a pas d'interfaces à implémenter. Les variables, les paramètres et les valeurs de retour des fonctions ne sont pas explicitement typés.

+ +

Java est un langage de programmation utilisant les classes, conçus pour être exécuté rapidement et garantir la sûreté du typage. Cela signifie par exemple qu'il n'est pas possible de transformer un entier Java en un objet ou qu'on ne peut pas accéder à des caractéristiques privées en corrompant le bytecode Java. Le modèle de classes utilisé par Java signifie qu'un programme n'est constitué que de classes et de méthodes. Cet héritage à base de classes, associé au typage fort font qu'on obtient des structures et des hiérarchies d'objets fortement couplées. Pour ces raisons, Java peut apparaître comme un langage plus complexe que JavaScript.

+ +

À l'inverse, JavaScript est un descendant de langages plus légers, dynamiquement typés tels que HyperTalk et dBASE. Ces langages de scripts visent un public plus large avec une syntaxe plus simple, des fonctionnalités natives spécialisées et des prérequis minimaux pour pouvoir créer des objets.

+ + + + + + + + + + + + + + + + + + + +
Comparaison synthétique entre JavaScript et Java
JavaScriptJava
Orienté objet. Aucune distinction entre les types et les objets. L'héritage est basé sur un mécanisme utilisant les prototypes et les propriétés et méthodes peuvent être ajoutées dynamiquement à n'importe quel objet.Orienté objet, utilisant un modèle de classes. Les objets sont divisés entre les classes et les instances, l'héritage s'effectue via la hiérarchie des classes. Les classes et les instances ne peuvent pas recevoir de nouvelles propriétés ou méthodes dynamiquement.
Le type de données des variables n'est pas déclaré (typage dynamique).Le type de données des variables doit être déclaré (typage statique).
+ +

Pour plus d'informations sur les différences entre JavaScript et Java, voir le chapitre sur les détails du modèle objet JavaScript.

+ +

JavaScript et la spécification ECMAScript

+ +

JavaScript est standardisé par Ecma International — une association européenne de standardisation des systèmes d'information et de communication (ECMA étant historiquement un acronyme pour European Computer Manufacturers Association) qui délivre un langage de programmation standardisé, international appelé ECMAScript. Ce langage se comporte de la même façon pour toutes les applications qui supportent ce standard. Les entreprises peuvent utiliser ce langage standard afin de développer leur implémentation de JavaScript. Le standard ECMAScript est documenté avec la spécification ECMA-262. Voir la page Nouveautés de JavaScript pour en savoir plus sur les différentes versions de JavaScript et les différentes éditions de la spécification ECMAScript.

+ +

Le standard ECMA-262 est également approuvé par l'ISO (International Organization for Standardization) sous ISO-16262. La spécification peut également être trouvée sur le site web d'Ecma International. La spécification ECMAScript ne décrit pas le Document Object Model (DOM) qui est standardisé par le World Wide Web Consortium (W3C) et le WHATWG (Web Hypertext Application Technology Working Group). Le DOM définit la façon dont les documents HTML sont exposés aux scripts. Pour mieux comprendre les différentes technologies gravitant autour de JavaScript, voir l'article Aperçu des technologies JavaScript.

+ +

Documentation JavaScript et spécification ECMAScript

+ +

La spécification ECMAScript est un ensemble de conditions à respecter pour implémenter ECMAScript : cela est utile lorsqu'on souhaite implémenter des fonctionnalités standard du langage au sein d'une implémentation ou d'un moteur ECMAScript (tel que SpiderMonkey pour Firefox, ou V8 pour Chrome).

+ +

La spécification ECMAScript n'a pas pour but d'aider les développeurs à écrire des scripts. La documentation JavaScript permet d'obtenir des informations pour écrire des scripts JavaScript.

+ +

La spécification ECMAScript utilise parfois une terminologie et une syntaxe qui peuvent sembler étranges aux yeux d'un développeur JavaScript. Bien que la description du langage diffère entre ECMAScript et la documentation JavaScript, le langage lui-même reste le même. JavaScript supporte l'ensemble des fonctionnalités mises en avant dans la spécification ECMAScript.

+ +

La documentation JavaScript décrit les aspects du langage qui pourront être utilisés par les développeurs JavaScript.

+ +

Démarrer avec JavaScript

+ +

Pour commencer à développer en JavaScript, c'est très simple : il suffit d'avoir un navigateur web récent. Ce guide inclut certaines fonctionnalités de JavaScript qui ne sont disponibles que dans les dernières versions de Firefox, il est donc recommandé d'utiliser une version de Firefox à jour pour essayer les exemples fournis.

+ +

Deux outils faisant partie de Firefox seront utiles pour expérimenter et tester du code JavaScript : la console web et l'ardoise JavaScript.

+ +

La console web

+ +

La console web affiche des informations sur la page actuellement chargée, elle dispose également d'une ligne de commande qui peut être utilisée pour exécuter des expressions JavaScript dans la page actuelle.

+ +

Pour ouvrir la console, dans le menu, sélectionner « Développement » puis « Console web » (en passant par la barre d'outils, ce sera « Outils » puis « Développement web » puis « Console web »). Avec le clavier, on pourra utiliser la combinaison de touche Ctrl+Shift+K sur Windows et Linux ou Cmd-Option-K sur Mac. Une fois lancée, la console apparaît en base de la fenêtre du navigateur. En bas de la zone occupée par la console, il y a une ligne de commande qui peut être utilisée pour saisir des instructions JavaScript, le résultat de ces instructions sera affiché dans le panneau au dessus :

+ +

Console web

+ +

L'ardoise JavaScript

+ +

La console est pratique quand il s'agit d'exécuter des instructions ligne par ligne. Cependant dès qu'on souhaite exécuter un script plus complexe de plusieurs lignes, la console devient vite limitée. Pour ça, on pourra utiliser l'ardoise JavaScript.

+ +

Pour accéder à l'ardoise JavaScript, dans le menu « Développement », sélectionner « Ardoise JavaScript » (via la barre d'outils, sélectionner « Outils », « Développement web » puis « Ardoise JavaScript »). Cela ouvrira une fenêtre séparée qui est un éditeur qui permet d'écrire et d'exécuter du code JavaScript dans le navigateur. Il est aussi possible de sauvegarder les scripts saisis dans l'ardoise dans des fichiers et de charger des scripts depuis les fichiers.

+ +

Si vous utilisez le bouton « Afficher », le code contenu dans l'ardoise sera exécuté par le navigateur et le résultat sera affiché sous forme d'un commentaire à la suite du code :

+ +

capture d'écran de l'ardoise JS

+ +

Coucou monde (hello world)

+ +

Pour commencer à écrire du JavaScript, ouvrez votre console web ou l'ardoise JavaScript et écrivez votre premier « Hello world » en JavaScript.

+ +
function saluer(utilisateur) {
+  return "Bonjour " + utilisateur;
+}
+
+saluer("Alice"); // "Bonjour Alice"
+
+ +

Dans les pages qui suivent, ce guide introduira la syntaxe du langage JavaScript ainsi que ses fonctionnalités ; vous pourrez ainsi écrire des applications plus complexes.

+ +

{{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Types_et_grammaire")}}

diff --git a/files/fr/web/javascript/guide/iterateurs_et_generateurs/index.html b/files/fr/web/javascript/guide/iterateurs_et_generateurs/index.html new file mode 100644 index 0000000000..d714b614cf --- /dev/null +++ b/files/fr/web/javascript/guide/iterateurs_et_generateurs/index.html @@ -0,0 +1,175 @@ +--- +title: Itérateurs et générateurs +slug: Web/JavaScript/Guide/iterateurs_et_generateurs +tags: + - Guide + - Intermediate + - JavaScript +translation_of: Web/JavaScript/Guide/Iterators_and_Generators +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Utiliser_les_promesses", "Web/JavaScript/Guide/Métaprogrammation")}}
+ +

Effectuer des traitements sur chacun des éléments d'une collection est une opération très fréquente. Il existe plusieurs outils natifs dans JavaScript pour parcourir une collection, les boucles for, map(), filter(). Les itérateurs et les générateurs font de ce concept d'itération une fonctionnalité principale du langage et permettent d'adapter et de personnaliser le comportement des boucles for...of.

+ +

Pour plus de détails sur les mécanismes d'itération, voir les pages suivantes :

+ + + +

Itérateurs

+ +

Un itérateur est un objet sachant comment accéder aux éléments d'une collection un par un et qui connait leur position dans la collection. En JavaScript, un itérateur expose une méthode next() qui retourne l'élément suivant dans la séquence. Cette méthode renvoie un objet possédant deux propriétés : done et value.

+ +

Un itérateur est "terminé" lorsque l'appel à la méthode next() renvoie un objet dont la propriété done vaut true.

+ +

Une fois créé, un itérateur peut être utilisé explicitement en appelant sa méthode next(), ou implicitement en utilisant la boucle for...in.

+ +

Voici un exemple d'une fonction créant un itérateur qui parcourt l'intervalle défini par ses arguments (depuis debut (inclus) jusqu'à end (exclus) et avec pas comme incrément. La valeur finale qui est renvoyée correspond à la taille de la séquence créée

+ +
function creerIterateurIntervalle(debut = 0, fin = Infinity, pas = 1) {
+  let prochainIndex = debut;
+  let nbIterations = 0;
+
+  const rangeIterator = {
+    next: function() {
+      let resultat;
+      if (prochainIndex < fin) {
+        resultat = { value: prochainIndex, done: false };
+        prochainIndex += pas;
+        nbIterations++;
+        return resultat;
+      }
+      return { value: nbIterations, done: true }
+    }
+  };
+  return rangeIterator;
+}
+ +

On pourra alors utiliser cette fonction et l'itérateur de la façon suivante :

+ +
let it = creerIterateurIntervalle(1, 10, 2);
+
+let resultat = it.next();
+while (!resultat.done) {
+ console.log(resultat.value); // 1 3 5 7 9
+ resultat = it.next();
+}
+
+console.log("La séquence parcourue contenait ", result.value, " éléments.");
+
+ +

Itérables

+ +

Un objet est considéré comme itérable s'il définit le comportement qu'il aura lors de l'itération (par exemple les valeurs qui seront utilisées dans une boucle {{jsxref("Instructions/for...of", "for...of")}}). Certains types natifs, tels qu'{{jsxref("Array")}} ou {{jsxref("Map")}}, possède un comportement par défaut pour les itérations, cependant d'autres types comme les Objets, ne possèdent pas ce comportement.

+ +

Pour qu'un objet soit itérable, un objet doit implémenter la méthode @@iterator, cela signifie que l'objet (ou un des objets de la chaîne de prototypes) doit avoir une propriété avec la clé {{jsxref("Symbol.iterator")}}. Cette fonction doit également, même si ce n'est pas une obligation, renvoyer une nouvel opérateur à chaque appel.

+ +

Itérables personnalisés

+ +

Il est possible de définir ses propres itérables de cette façon :

+ +
var monItérable = {};
+monItérable[Symbol.iterator] = function* () {
+    yield 1;
+    yield 2;
+    yield 3;
+};
+[...monItérable] // [1, 2, 3]
+
+ +

Itérables natifs

+ +

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}} et {{jsxref("Set")}} sont des itérables natifs car les prototypes de chacun ont tous une méthode {{jsxref("Symbol.iterator")}}.

+ +

Les éléments de syntaxe utilisant des itérables

+ +

Certaines instructions ou expressions utilisent des itérables, par exemple les boucles {{jsxref("Instructions/for...of","for...of")}} et {{jsxref("Opérateurs/yield*","yield*")}}.

+ +
for(let value of ["a", "b", "c"]){
+    console.log(value)
+}
+// "a"
+// "b"
+// "c"
+
+[..."abc"] // ["a", "b", "c"]
+
+function* gen(){
+  yield* ["a", "b", "c"]
+}
+
+gen().next() // { value:"a", done:false }
+
+[a, b, c] = new Set(["a", "b", "c"])
+a // "a"
+
+
+ +

Générateurs

+ +

Les itérateurs personnalisés sont un outil utile mais leur création peut s'avérer complexe et il faut maintenir leur état interne. Avec les générateurs, on peut définir une seule fonction qui est un algorithme itératif et qui peut maintenir son état.

+ +

Un générateur est un type de fonction spécial qui fonctionne comme une fabrique (factory) d'itérateurs. Une fonction devient un générateur lorsqu'elle contient une ou plusieurs expressions yield et qu'elle utilise la syntaxe function*.

+ +
function* idMaker(){
+  var index = 0;
+  while(true)
+    yield index++;
+}
+
+var gen = idMaker();
+
+console.log(gen.next().value); // 0
+console.log(gen.next().value); // 1
+console.log(gen.next().value); // 2
+// ...
+ +

Générateurs avancés

+ +

Les générateurs calculent les valeurs à fournir à la demande, ce qui leur permet de représenter efficacement des suites complexes à calculer, voire des séries infinies (comme vu dans l'exemple précédent).

+ +

La méthode next() accepte également un argument qui pourra être utilisé pour modifier l'état interne du générateur. Une valeur passée à next() sera traitée comme le résultat de la dernière expression yield qui a interrompu le générateur. Une valeur passée au premier appel de next() sera toujours ignorée.

+ +

Par exemple, on peut avoir un générateur pour la suite de Fibonnaci et utiliser next(x) pour redémarrer la série :

+ +
function* fibonacci(){
+  var fn1 = 0;
+  var fn2 = 1;
+  while (true){
+    var current = fn1;
+    fn1 = fn2;
+    fn2 = fn1 + current;
+    var reset = yield current;
+    if (reset){
+        fn1 = 0;
+        fn2 = 1;
+    }
+  }
+}
+
+var sequence = fibonacci();
+console.log(sequence.next().value);     // 0
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+console.log(sequence.next().value);     // 3
+console.log(sequence.next().value);     // 5
+console.log(sequence.next().value);     // 8
+console.log(sequence.next(true).value); // 0
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+ +

Il est possible de forcer un générateur à lever une exception en utilisant la méthode throw() en lui passant la valeur de l'exception en argument. Cette exception sera levée depuis l'état actuel du générateur, comme si le yield qui était en attente avait été une instruction throw valeur.

+ +

Si le mot-clé yield n'est pas trouvé lors de la levée de l'exception, l'exception sera propagée jusqu'à l'appel de throw(), les appels à next() qui suivent renverront une valeur dont la propriété done sera true.

+ +

Si l'exception n'est pas interceptée dans le générateur, elle se propagera jusqu'à l'appel de throw() et les appels suivants de next() renverront un objet dont la propriété done vaut true.

+ +

Les générateurs possèdent une méthode return(valeur) qui permet de renvoyer une valeur donnée et de terminer le générateur.

+ +

{{PreviousNext("Web/JavaScript/Guide/Utiliser_les_promesses", "Web/JavaScript/Guide/Métaprogrammation")}}

diff --git a/files/fr/web/javascript/guide/javascript_overview/index.html b/files/fr/web/javascript/guide/javascript_overview/index.html new file mode 100644 index 0000000000..095f85f2dd --- /dev/null +++ b/files/fr/web/javascript/guide/javascript_overview/index.html @@ -0,0 +1,117 @@ +--- +title: Aperçu de JavaScript +slug: Web/JavaScript/Guide/JavaScript_Overview +tags: + - Guide + - Intermediate + - JavaScript +translation_of: Web/JavaScript/Guide/Introduction +--- +

{{jsSidebar("JavaScript Guide")}}

+

Ce chapitre est une introduction à JavaScript et détaille quelques-uns des concepts fondamentaux de ce langage.

+

Qu'est-ce que JavaScript ?

+

JavaScript est un langage de script, multi-plateforme, orienté-objet. JavaScript est un langage compact, léger. Il n'est pas conçu pour être utilisé de manière autonome, mais pour être intégré dans d'autres produits et applications tels que les navigateurs web. Dans un environnement hôte, JavaScript peut servir d'interface de manipulation avec les objets mis à disposition par l'environnement.

+

Le noyau du langage JavaScript contient un ensemble d'objets, tels que Array, Date, et Math, et un noyau d'éléments comme les opérateurs, structures de contrôle et déclarations. Le cœur de JavaScript peut être étendu pour remplir différents besoins grâce à des objets additionnels. Par exemple :

+ +

Grâce à la fonctionnalité LiveConnect, JavaScript peut faire communiquer du code Java avec JavaScript. À partir de JavaScript, on peut instancier des objets Java et accéder à leurs méthodes publiques et attributs. À partir de Java, on peut accéder des objets, propriétés et méthodes JavaScript.

+

Netscape inventa JavaScript et fut le premier navigateur à l'utiliser.

+

JavaScript et Java

+

JavaScript et Java sont semblables en ce qui concerne quelques aspects mais restent fondamentalement différents. JavaScript ressemble à Java, mais il ne possède pas un typage fort et statique. JavaScript suit la syntaxe de la plupart des expressions Java, les conventions de nommage et les structures de flots de contrôle basiques. C'est pour cette raison qu'il a été renommé de LiveScript en JavaScript.

+

En contraste avec le système compile-time des classes construites par des déclarations, JavaScript supporte les systèmes runtime basés sur un petit nombre de types de données représentant des valeurs numériques, booléennes et des chaines de caractères. JavaScript possède un modèle objet basé sur des prototypes au lieu du modèle objet traditionnel. Le modèle basé sur le prototype offre un héritage dynamique. Cela signifie que ce qui est hérité peut varier selon les objets. JavaScript supporte aussi l'écriture de fonctions sans qu'il y ait besoin de déclarations spéciales. Les fonctions peuvent être des propriétés d'objets, exécutées comme des méthodes avec un typage souple.

+

JavaScript est un langage beaucoup plus souple que Java. Il n'est pas nécessaire de déclarer toutes les variables, classes, et méthodes. Il n'y a pas à se soucier qu'une méthode soit publique, privée ou protégée, il n'y a pas à implémenter d'interfaces. Les variables, paramètres et types de retour des fonctions ne sont pas explicitement typés.

+

Java est un langage de programmation basé sur les classes conçues pour une exécution rapide et un typage sûr. La sûreté du typage signifie qu'on ne peut pas transformer un entier en Java en une référence vers un objet ni accéder à la mémoire privée via une corruption du bytecode Java. Le modèle de Java, basé sur les classes, signifie que les programmes se composent exclusivement de classes et de leurs méthodes. L'héritage des classes en Java ainsi que le typage fort exigent généralement une hiérarchie d'objets étroitement couplée. Ces exigences font que la programmation en Java peut s'avérer plus complexe que JavaScript.
+
+ En revanche, JavaScript vient d'une lignée de langages plus légers, dynamiquement typés comme HyperTalk et dBASE. Ces langages de script offrent des outils de programmation à un public beaucoup plus large en raison de leur syntaxe plus facile, des fonctionnalités spécialisées intégrées et des exigences minimales pour la création d'objets.

+

Table 1.1 Comparaison entre JavaScript et Java

+ + + + + + + + + + + + + + + + + + + + + + +
+ Tableau 1.1 Comparaison entre JavaScript et Java
JavaScriptJava
Orienté objet. Pas de distinction entre les types d'objets. L'héritage se fait à travers le mécanisme de prototype et les propriétés et méthodes peuvent être ajoutées à n'importe quel objet dynamique.Basé sur classes. Les objets sont divisés en classes et instances avec une hiérarchie d'héritage. Les classes et les instances ne peuvent pas avoir des propriétés ou des méthodes ajoutées dynamiquement.
Les types des variables ne sont pas déclarés (typage dynamique).Les types des variables doivent être déclarés (typage statique).
On ne peut pas écrire automatiquement sur le disque dur.On ne peut pas écrire automatiquement sur le disque dur.
+

Pour plus d'informations sur la différence entre JavaScript et Java, voir les détails au chapitre du modèle objet de JavaScript.

+

JavaScript et la spécification ECMAScript

+

Netscape a inventé JavaScript et JavaScript a d'abord été utilisé dans les navigateurs Netscape. Cependant, Netscape travailla avec Ecma International - l'association européenne pour la normalisation des systèmes d'information et de communication (ECMA était autrefois un acronyme pour European Computer Manufacturers Association), afin de fournir un standard et un langage de programmation international basée sur le noyau JavaScript. Cette version standardisée de JavaScript, appelée ECMAScript, se comporte de la même façon dans toutes les applications qui prennent en charge la norme. Les entreprises peuvent utiliser le langage standard ouvert pour développer leur implémentation de JavaScript. La norme ECMAScript est documentée dans la spécification ECMA-262.
+
+ La norme ECMA-262 est également approuvée par l'ISO (Organisation internationale de normalisation) en tant que norme ISO-16262. Vous pouvez trouver une version PDF de la norme ECMA-262 (version obsolète) sur le site de Mozilla. Vous pouvez également trouver les spécifications sur le site de l'Ecma International. La spécification ECMAScript ne décrit pas le Document Object Model (DOM), qui est standardisé par le World Wide Web Consortium (W3C). Le DOM définit la manière dont les objets des documents HTML sont exposés à votre script.

+

Relation entre les versions de JavaScript et les éditions d'ECMAScript

+

Netscape a travaillé en étroite collaboration avec Ecma International afin de produire la spécification ECMAScript (ECMA-262). Le tableau suivant décrit la relation entre les versions de JavaScript et les éditions d'ECMAScript.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Tableau 1.2 Les versions de JavaScript et les liens avec les versions ECMAScript
Version de JavaScriptLien avec l'édition d'ECMAScript
JavaScript 1.1ECMA-262, Édition 1 basée sur JavaScript 1.1.
JavaScript 1.2 +

ECMA-262 n'était pas terminée lorsque JavaScript 1.2 est sorti. JavaScript 1.2 n'est pas entièrement compatible avec la norme ECMA-262, édition 1, pour les raisons suivantes :

+
    +
  • Netscape a développé des fonctionnalités supplémentaires dans JavaScript 1.2 qui n'ont pas été prises en considération pour ECMA-262.
  • +
  • ECMA-262 ajoute deux nouvelles fonctionnalités : l'internationalisation en utilisant le comportement Unicode et uniforme sur toutes les plateformes. Plusieurs fonctionnalités de JavaScript 1.2, telles que l'objet Date, qui étaient dépendantes de la plateforme.
  • +
+
JavaScript 1.3JavaScript 1.3 est entièrement compatible avec la norme ECMA-262, édition 1.
+ JavaScript 1.3 a résolu les contradictions que JavaScript 1.2 a eu avec ECMA-262, tout en conservant toutes les fonctionnalités supplémentaires de JavaScript 1.2, sauf == et! =, qui ont été modifiées pour se conformer à la norme ECMA-262.
JavaScript 1.4JavaScript 1.4 est entièrement compatible avec la norme ECMA-262, édition 1.
+ La troisième version de la spécification ECMAScript n'a pas été finalisée lorsque JavaScript 1.4 est sorti.
JavaScript 1.5JavaScript 1.5 est entièrement compatible avec la spécification ECMA-262, édition 3.
+
+

Remarque : ECMA-262 dans sa deuxième édition contenait des modifications mineures et corrections de bugs selon la spécification Édition 1. La version actuelle par le groupe de travail TC39 d'Ecma International est ECMAScript Edition 5.1

+
+

La référence JavaScript indique les fonctionnalités du langage qui sont conformes à ECMAScript.

+

JavaScript inclut toujours des fonctionnalités qui ne font pas partie de la spécification ECMAScript. JavaScript est compatible avec ECMAScript, tout en offrant des fonctionnalités supplémentaires.

+

Documentation de JavaScript et spécification ECMAScript

+

La spécification ECMAScript est un ensemble d'exigences pour la mise en œuvre ECMAScript. Elle est utile pour savoir si une fonctionnalité JavaScript est prise en charge dans d'autres implémentations ECMAScript. Si vous prévoyez d'écrire du code JavaScript qui utilise des fonctionnalités prises en charge par ECMAScript seulement, alors il vous sera peut-être nécessaire de revoir la spécification ECMAScript.
+
+ Le document ECMAScript n'est pas destiné à aider les programmeurs de script : c'est le but de la documentation JavaScript.

+

Terminologie JavaScript et ECMAScript

+

La spécification ECMAScript utilise une syntaxe et une terminologie qui peuvent ne pas être familières à un programmeur JavaScript. Bien que la description du langage puisse varier en ECMAScript, le langage lui-même reste le même. JavaScript prend en charge toutes les fonctionnalités décrites dans la spécification ECMAScript.

+

La documentation JavaScript décrit les aspects du langage qui sont appropriés pour un programmeur JavaScript. Par exemple :

+ +

« Précédent  Suivant »

+

 

diff --git "a/files/fr/web/javascript/guide/le_mod\303\250le_objet_javascript_en_d\303\251tails/index.html" "b/files/fr/web/javascript/guide/le_mod\303\250le_objet_javascript_en_d\303\251tails/index.html" new file mode 100644 index 0000000000..50a78fdf27 --- /dev/null +++ "b/files/fr/web/javascript/guide/le_mod\303\250le_objet_javascript_en_d\303\251tails/index.html" @@ -0,0 +1,747 @@ +--- +title: Le modèle objet JavaScript en détails +slug: Web/JavaScript/Guide/Le_modèle_objet_JavaScript_en_détails +tags: + - Guide + - Intermediate + - JavaScript + - Object +translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Utiliser_les_objets", "Web/JavaScript/Guide/Utiliser_les_promesses")}}

+ +

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.

+ +

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.

+ +

Langages de prototypes / Langages de classes

+ +

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.

+ + + +

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 prototypiques 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 prototype d’un autre objet, auquel cas le second objet partage les propriétés du premier.

+ +

La définition d'une classe

+ +

Dans les langages de classes, on doit définir une classe dans une définition de classe. Dans cette définition, on peut inclure certaines méthodes spéciales, comme les constructeurs 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 new, utilisé avec le constructeur, permet de créer de nouvelles instances.

+ +

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 new doit être utilisé avec un constructeur pour créer un nouvel objet.

+ +
+

Note : Bien qu'ECMAScript 2015 introduise une déclaration de classe, 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.

+
+ +

Classes-filles et héritage

+ +

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 Employé comprend les propriétés nom et branche et que Manager est une classe-fille de la classe Employee qui ajoute la propriété rapports. Dans cet exemple, une instance de la classe Manager aurait trois propriétés : nom, branche, et rapports.

+ +

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 EmployéManager mais on utilisera une terminologie légèrement différente. Tout d’abord, on définit le constructeur (fonction) Employé et on y définit les propriétés nom et branche. Ensuite, on définit le constructeur Manager avec la propriété rapports. Enfin, on assigne un nouvel objet Employé comme prototype dans le constructeur Manager. Ainsi, quand on créera un nouvel objet Manager, il héritera des propriétés nom et branche de l’objet Employé.

+ +

Ajouter ou retirer des propriétés

+ +

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é.

+ +

Résumé des différences

+ +

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.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CatégorieLangage de classe (Java)Langage de prototype (JavaScript)
Classe ou instanceLes classes et les instances sont deux entités distinctes.Tous les objets sont des instances.
DéfinitionUne classe est définie avec une définition de classe. On instancie une classe avec des méthodes appelées constructeursOn définit et on crée un ensemble d’objets avec des fonctions qui sont des constructeurs.
Création d'un nouvel objetOn crée un seul objet grâce à l’opérateur new.Même chose que pour les langages de classe.
Construction de la hiérarchie des objetsOn construit une hiérarchie d’objets en utilisant les définitions des classes pour définir des classes-filles à partir de classes existantes.On construit une hiérarchie d’objets en assignant un prototype à un objet dans le constructeur de cet objet.
Modèle d'héritageLes objets héritent des propriétés appartenant à la chaîne des classes de la hiérarchie.Les objets héritent des propriétés appartenant à la chaîne des prototypes de la hiérarchie.
Ajout de propriétésLa 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.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.
+ +

L’exemple de l’employé

+ +

La suite de ce chapitre expliquera la hiérarchie objet suivante, modélisant un système avec différents employés :

+ +

+ +

Une hiérarchie objet basique

+ +

Cet exemple utilisera les objets suivants :

+ + + +

La création de la hiérarchie

+ +

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.

+ +

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.

+ +

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 Des constructeurs plus flexibles). Ici, ces définitions nous permettent d’observer l’héritage.

+ +
+

Attention, quand on assigne une fonction directement à NomFonction.prototype, cela retire la propriété « constructeur » du prototype original. Ainsi, (new Travailleur).constructor renverra un Employé (et non pas Travailleur). 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 ».

+
+ +

Les définitions d’Employé 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.

+ + + + + + + + + + + + + + +
JavaScriptJava
+
+function Employé () {
+  this.nom = "";
+  this.branche = "commun";
+}
+
+
+
+public class Employé {
+   public String nom;
+   public String branche;
+   public Employé () {
+      this.nom = "";
+      this.branche = "commun";
+   }
+}
+
+
+ +

Les définitions de Manager et Travailleur 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é prototype de la fonction constructeur (autrement dit, on définit la valeur de la propriété prototype de la fonction, en utilisant une instance du prototype utilisé puis en surchargeant prototype.constructor). 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.

+ + + + + + + + + + + + + + +
JavaScriptJava
+
+function Manager () {
+  this.rapports = [];
+}
+Manager.prototype = new Employé;
+
+function Travailleur () {
+  this.projets = [];
+}
+Travailleur.prototype = new Employé;
+
+
+
+public class Manager extends Employé {
+   public Employé[] rapports;
+   public Manager () {
+      this.rapports = new Employé[0];
+   }
+}
+
+public class Travailleur extends Employé {
+   public String[] projets;
+   public Travailleur () {
+      this.projets = new String[0];
+   }
+}
+
+
+ +

Les définitions d’Ingénieur et de Vendeur permettent de créer des objets qui héritent de Travailleur et donc, implicitement, de Employé. 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é branche avec des valeurs spécifiques.

+ + + + + + + + + + + + + + +
JavaScriptJava
+
+function Vendeur () {
+   this.branche = "ventes";
+   this.quota = 100;
+}
+Vendeur.prototype = new Travailleur;
+
+function Ingénieur () {
+   this.branche = "ingénierie";
+   this.moteur = "";
+}
+Ingénieur.prototype = new Travailleur;
+
+
+
+public class Vendeur extends Travailleur {
+   public double quota;
+   public Vendeur () {
+      this.branche = "ventes";
+      this.quota = 100.0;
+   }
+}
+
+public class Ingénieur extends Travailleur {
+   public Ingénieur () {
+      this.branche = "ingénierie";
+      this.moteur = "";
+   }
+}
+
+
+ +

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.

+ +
+

Le terme instance 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 parent, enfant, ancêtre, et descendant 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.

+
+ +

Créer des objets avec des définitions simples

+ +

Les propriétés d’un objet

+ +

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.

+ +

L’héritage de propriétés

+ +

Imaginons qu’on souhaite créer un objet marc qui est un Travailleur :

+ +
var marc = new Travailleur;
+
+ +

Lorsque JavaScript rencontre l’opérateur new, un objet générique est créé, ce nouvel objet est passé comme valeur de this à la fonction constructeur de Travailleur. Le constructeur définit ensuite la valeur de la propriété projets puis il définit implicitement la valeur de la propriété interne [[Prototype]] avec la valeur de Travailleur.prototype. (Le nom de cette propriété commence et finit par deux tirets bas.) La propriété __proto__ 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 marc à cet objet.

+ +

En utilisant ce procédé, on n’introduit pas de valeurs spécifiques pour les propriétés de marc 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é __proto__. 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 marc : on aura les propriétés suivantes avec les valeurs respectives :

+ +
marc.nom = "";
+marc.branche = "commun";
+marc.projets = [];
+
+ +

L’objet marc hérite des valeurs des propriétés nom et branche via le constructeur Employé. Il y a une valeur locale pour la propriété projets grâce au constructeur Travailleur.

+ +

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 Travailleur. On peut, bien sûr, changer les valeurs de ces propriétés pour fournir des valeurs spécifiques :

+ +
marc.nom = "Marc Dupont";
+marc.branche = "admin";
+marc.projets = ["navigateur"];
+ +

L’ajout de propriétés

+ +

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 :

+ +
marc.bonus = 3000;
+
+ +

Désormais, l’objet marc possède la propriété bonus. En revanche, aucun autre Travailleur ne possède cette propriété.

+ +

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é spécialité à tous les employés grâce à l’instruction suivante :

+ +
Employé.prototype.spécialité = "aucune";
+
+ +

Dès que l’instruction est exécutée par JavaScript, l’objet marc possèdera aussi la propriété spécialité initialisée avec la valeur "aucune". Le schéma suivant décrit l’effet de cet ajout puis de la surcharge de cette propriété pour le prototype Ingénieur.

+ +


+ Ajouter des propriétés

+ +

Des constructeurs plus flexibles

+ +

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.

+ +


+ Définir les propriétés grâce au constructeur

+ +

Le tableau suivant montre les définitions de ces objets en JavaScript et en Java.

+ + + + + + + + + + + + + + + + + + + + + + +
JavaScriptJava
+
+function Employé (nom, branche) {
+  this.nom = nom || "";
+  this.branche = branche || "commun";
+}
+
+
+
+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;
+   }
+}
+
+
+
+function Travailleur (projs) {
+  this.projets = projs || [];
+}
+Travailleur.prototype = new Employé;
+
+
+
+public class Travailleur extends Employé {
+   public String[] projets;
+   public Travailleur () {
+      this(new String[0]);
+   }
+   public Travailleur (String[] projs) {
+      this.projets = projs;
+   }
+}
+
+
+
+
+
+function Ingénieur (moteur) {
+   this.branche = "ingénierie";
+   this.moteur = moteur || "";
+}
+Ingénieur.prototype = new Travailleur;
+
+
+
+public class Ingénieur extends Travailleur {
+   public String moteur;
+   public Ingénieur () {
+      this.branche = "ingénierie";
+      this.moteur = "";
+   }
+   public Ingénieur (String moteur) {
+      this.branche = "ingénierie";
+      this.moteur = moteur;
+   }
+}
+
+
+ +

Les définitions JavaScript présentées ci-dessus utilisent une instruction qui peut paraître étrange pour avoir des valeurs par défaut :

+ +
this.nom = nom || "";
+
+ +

L’opérateur correspondant au OU logique en JavaScript (||) évalue le premier argument. Si cet argument peut être converti en true, 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 (nom) 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.

+ +
+

Attention, cela peut ne pas fonctionner comme souhaité si le constructeur est appelé avec des arguments qui seront convertis à false (comme 0 (zéro) et la chaîne de caractère vide (""). Si ces valeurs sont utilisées, la valeur par défaut sera prise en compte.

+
+ +

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 :

+ +
var jeanne = new Ingénieur("carnot");
+ +

Les propriétés de l’objet sont donc désormais :

+ +
jeanne.nom == "";
+jeanne.branche == "ingénierie";
+jeanne.projets == [];
+jeanne.moteur == "carnot"
+
+ +

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 nom ici. Si on souhaite définir des valeurs initiales pour ces propriétés, il faut modifier légèrement le constructeur.

+ +

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.

+ +


+ La définition de propriétés héritées dans un constructeur

+ +

Ainsi, le constructeur de Ingénieur sera :

+ +
function Ingénieur (nom, projets, moteur) {
+  this.base = Travailleur;
+  this.base(nom, "ingénierie", projets);
+  this.moteur = moteur || "";
+}
+
+ +

Si on crée ensuite un objet Ingénieur de cette façon :

+ +
var jeanne = new Ingénieur("Jeanne Dubois", ["navigateur", "javascript"], "carnot");
+
+ +

L’exécution du code entraînera les étapes suivantes :

+ +
    +
  1. La création d’un objet générique avec l'opérateur new qui assigne la valeur Ingénieur.prototype à la propriété __proto__.
  2. +
  3. L'opérateur new passe ensuite l’objet au constructeur Ingénieur comme valeur du mot-clé this.
  4. +
  5. Le constructeur crée une nouvelle propriété, appelée base, pour cet objet. Cette propriété reçoit la valeur du constructeur Travailleur. Ainsi le constructeur Travailleur devient une méthode de l’objet Ingénieur. Le nom de cette propriété base n’est pas spécial, on pourrait utiliser un autre nom pour cette propriété (sous réserve qu’il soit valide).
  6. +
  7. +

    Le constructeur appelle la méthode base et lui passe deux arguments qui avaient été passés ("Jeanne Dubois" et ["navigateur", "javascript"]), ainsi que la chaîne de caractères "ingénierie". Le fait d’utiliser "ingénierie" explicitement indique que tous les objets Ingénieur auront la même valeur pour la propriété branche qui aura été héritée. Cela permet également de surcharger la valeur par défaut héritée de Employé.

    +
  8. +
  9. +

    base étant une méthode d'Ingénieur, lors de l'appel de cette fonction, le mot clé this aura été lié à l'objet créé en 1. Ainsi, la fonction Travailleur passera les arguments "Jeanne Dubois" et "ingénierie" au constructeur Employé. Une fois que la fonction constructeur Employé a renvoyé un résultat, la fonction Travailleur utilise l'argument restant pour donner la valeur à la propriété projets.

    +
  10. +
  11. Une fois que la méthode base a renvoyé un résultat, le constructeur Ingénieur initialise la propriété moteur avec la valeur "carnot".
  12. +
  13. Lorsque le constructeur renvoie le résultat, il est assigné à la variable jeanne.
  14. +
+ +

On peut penser qu’un simple appel au constructeur Travailleur, dans le constructeur Ingénieur permette de définir l'héritage pour les objets Ingénieur. Attention, ce n’est pas le cas. Un simple appel au constructeur Travailleur 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 Employé ou Travailleur : l'objet Ingénieur n’en héritera pas. Si par exemple on a :

+ +
function Ingénieur (nom, projets, moteur) {
+  this.base = Travailleur;
+  this.base(nom, "ingénierie", projets);
+  this.moteur = moteur || "";
+}
+var jeanne = new Ingénieur("Jeanne Dubois", ["navigateur", "javascript"], "carnot");
+Employé.prototype.spécialité = "aucune";
+
+ +

L'objet jeanne n’héritera pas de la propriété spécialité. Il aurait fallu préciser le prototype pour s'assurer de l'héritage dynamique. Si on a plutôt :

+ +
function Ingénieur (nom, projets, moteur) {
+  this.base = Travailleur;
+  this.base(nom, "ingénierie", projets);
+  this.moteur = moteur || "";
+}
+Ingénieur.prototype= new Travailleur;
+var jeanne = new Ingénieur("Jeanne Dubois", ["navigateur", "javascript"], "carnot");
+Employé.prototype.spécialité = "aucune";
+
+ +

Alors la valeur de la propriété spécialité de jeanne sera "aucune".

+ +

Une autre façon d’utiliser l’héritage dans un constructeur peut être d'utiliser les méthodes call() et apply(). Les deux fragments de codes présentés ici sont équivalents :

+ + + + + + + + +
+
+function Ingénieur (nom, projets, moteur) {
+  this.base = Travailleur;
+  this.base(nom, "ingénierie", projets);
+  this.moteur = moteur || "";
+}
+
+
+
+function Ingénieur (nom, projets, moteur) {
+  Travailleur.call(this, nom, "ingénierie", projets);
+  this.moteur = moteur || "";
+}
+
+
+ +

En utilisant la méthode call() on obtient une syntaxe plus claire car on n’utilise plus la propriété intermédiaire base.

+ +

L’héritage de propriétés : les subtilités

+ +

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.

+ +

Valeurs locales et valeurs héritées

+ +

Quand on accède à la propriété d’un objet, JavaScript effectue les étapes suivantes :

+ +
    +
  1. On vérifie si la valeur existe localement : si c'est le cas on renvoie cette valeur.
  2. +
  3. S'il n’y a pas de valeur locale, on parcourt la chaîne des prototypes grâce à la propriété__proto__.
  4. +
  5. Si un objet de la chaîne de prototypes possède une valeur pour la propriété recherchée, alors on renvoie cette valeur.
  6. +
  7. Si aucune propriété correspondante n’est trouvée, alors l’objet ne possède pas cette propriété.
  8. +
+ +

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 :

+ +
function Employé () {
+  this.nom = "";
+  this.branche = "commun";
+}
+
+function Travailleur () {
+  this.projets = [];
+}
+Travailleur.prototype = new Employé;
+
+ +

Si on utilise ces définitions et qu'on définit une instance de Travailleur appelée amy avec l'instruction suivante :

+ +
var amy = new Travailleur;
+
+ +

Alors l'objet amy possède une propriété locale : projets. Les valeurs des propriétés nom et branche ne sont pas locales, elles sont obtenues grâce à la propriété __proto__ de l'objet amy. Ainsi amy possède les propriétés suivantes avec les valeurs respectives :

+ +
amy.nom == "";
+amy.branche == "commun";
+amy.projets == [];
+
+ +

Si maintenant on change la valeur de la propriété nom pour le prototype associé à Employé :

+ +
Employé.prototype.nom = "Inconnu"
+
+ +

On pourrait penser que cette nouvelle valeur est propagée pour toutes les instances de Employé. Ce n’est pas le cas.

+ +

En effet, lorsqu’on crée n’importe quelle instance de Employé, cette instance obtient une valeur locale pour la propriété nom (qui est la chaîne de caractères vide). Cela signifie que lorsqu'on utilise le prototype Travailleur dans lequel on crée un nouvel objet Employé, Travailleur.prototype aura une valeur locale pour la propriété nom. Ainsi, quand JavaScript recherche la propriété nom de l'objet amy (qui est une instance de Travailleur), JavaScript trouve la valeur locale de cette propriété au niveau de Travailleur.prototype et ne remonte pas plus loin dans la chaîne : on n’atteint pas Employé.prototype.

+ +

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 :

+ +
function Employé () {
+  this.branche = "commun"; // La propriété this.nom, qui est une variable locale, n'apparaît pas ici
+}
+Employé.prototype.nom = ""; // Il s'agit d'une simple affectation
+
+function Travailleur () {
+  this.projets = [];
+}
+Travailleur.prototype = new Employé;
+
+var amy = new Travailleur;
+
+Employé.prototype.nom = "Inconnnu";
+
+ +

Alors on aura bien la propriété nom de amy qui deviendra "Inconnu".

+ +

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.

+ +

Comment déterminer les relations entre les instances

+ +

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 __proto__ et ainsi de suite pour explorer la chaîne des prototypes.

+ +

La propriété spéciale __proto__ est défnie à la construction d'un objet et contient la valeur du constructeur de la propriétéprototype. Ainsi, l’expression new Toto() crée un nouvel objet avec __proto__ == Toto.prototype. Ainsi, tous les changements des propriétés de Toto.prototype sont propagés sur la chaîne des prototypes des objets ayant été créés par new Toto().

+ +

Chaque objet (sauf Object) possède une propriété __proto__. Chaque fonction possède une propriété prototype. Ainsi, on peut relier les objets par « héritage prototypique ». Pour tester l’héritage, on peut comparer la propriété __proto__ d'un objet avec la propriété prototype d'une fonction. JavaScript permet de faire ceci avec l’opérateur instanceof qui teste un objet par rapport à une fonction et qui renvoie true si l’objet hérite de la fonction prototype. Ainsi :

+ +
var t = new Toto();
+var isTrue = (t instanceof Toto);
+ +

Pour avoir un exemple plus précis, si on crée un objet Ingénieur comme ceci :

+ +
var chris = new Engineer("Chris Pigman", ["jsd"], "fiji");
+
+ +

L’ensemble des instructions suivantes renverra true :

+ +
chris.__proto__ == Ingénieur.prototype;
+chris.__proto__.__proto__ == Travailleur.prototype;
+chris.__proto__.__proto__.__proto__ == Employé.prototype;
+chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
+chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
+
+ +

On pourrait donc écrire la une fonction instanceOf de la façon suivante :

+ +
function instanceOf(object, constructor) {
+   while (object != null) {
+      if (object == constructor.prototype)
+         return true;
+      if (typeof object == 'xml') {
+        return constructor.prototype == XML.prototype;
+      }
+      object = object.__proto__;
+   }
+   return false;
+}
+
+ +
Note : 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.
+ +

Ainsi, avec cette fonction, les expressions suivantes seront vérifiées :

+ +
instanceOf (chris, Ingénieur)
+instanceOf (chris, Travailleur)
+instanceOf (chris, Employé)
+instanceOf (chris, Object)
+
+ +

En revanche, l’expression qui suit est fausse :

+ +
instanceOf (chris, Vendeur)
+
+ +

Les informations globales dans les constructeurs

+ +

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 :

+ +
var idCompteur = 1;
+
+function Employé (nom, branche) {
+   this.nom = nom || "";
+   this.branche = branche || "commun";
+   this.id = idCompteur++;
+}
+
+ +

Avec cette définition, si on utilise les instructions suivantes victoria.id sera 1 et henri.id sera 2:

+ +
var victoria = new Employé("Victoria Rander", "international")
+var henri = new Employé("Henri Jelier", "ventes")
+
+ +

De cette façon, on peut penser que cette solution convient. Cependant, idCompteur sera incrémenté à chaque fois qu’un objet Employé sera créé, quelqu’en soit la raison. Si on utilise la hiérarchie établie au cours de ce chapitre, le constructeur Employé sera appelé à chaque fois qu’on définit un prototype. Avec le code suivant par exemple :

+ +
var idCompteur = 1;
+
+function Employé (nom, branche) {
+   this.nom = nom || "";
+   this.branche = branche || "commun";
+   this.id = idCompteur++;
+}
+
+function Manager (nom, branche, rapports) {...}
+Manager.prototype = new Employé;
+
+function Travailleur (nom, branche, projets) {...}
+Travailleur.prototype = new Employé;
+
+function Ingénieur (nom, projets, moteur) {...}
+Ingénieur.prototype = new Travailleur;
+
+function Vendeur (nom, projets, quota) {...}
+Vendeur.prototype = new Travailleur;
+
+var alex = new Ingénieur("Alex S");
+
+ +

Si on prend le cas où les définitions utilisent la propriété base et appellent le constructeur à chaque fois au-dessus, alors la propriété alex.id vaudra 3.

+ +

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 :

+ +
function Employé (nom, branche) {
+   this.nom = nom || "";
+   this.branche = branche || "commun";
+   if (nom)
+      this.id = idCompteur++;
+}
+
+ +

Lorsqu’on crée une instance d’Employé 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, alex.id vaudrait 1.

+ +

Une autre façon de procéder est de créer une copie du prototype d'Employé et d'affecter celle-ci à Travailleur :

+ +
Travailleur.prototype = Object.create(Employé.prototype);
+// plutôt que Travailleur.prototype = new Employé;
+ +

L’absence d’héritage multiple

+ +

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.

+ +

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.

+ +

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 :

+ +
function Passioné (passion) {
+   this.passion = passion || "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 || "";
+}
+Ingénieur.prototype = new Travailleur;
+
+var denis = new Ingénieur("Denis Carle", ["collabra"], "carnot")
+
+ +

Supposons que la définition de Travailleur soit utilisée plus haut dans ce chapitre. Dans ce cas, l’objet dennis aura les propriétés suivantes :

+ +
denis.nom == "Denis Carle"
+denis.branche == "ingénierie"
+denis.projets == ["collabra"]
+denis.moteur == "carnot"
+denis.passion == "plongée"
+
+ +

On voit bien que denis bénéficie de la propriété passion du constructeur Passioné. Cependant, si, plus tard, on ajoute une propriété au prototype du constructeur :

+ +
Passioné.prototype.équipement = ["masque", "filet", "club", "balles"]
+
+ +

L’objet denis n’héritera pas de cette nouvelle propriété.

+ +

{{PreviousNext("Web/JavaScript/Guide/Utiliser_les_objets", "Web/JavaScript/Guide/Utiliser_les_promesses")}}

diff --git "a/files/fr/web/javascript/guide/le_protocole_it\303\251rateur_historique/index.html" "b/files/fr/web/javascript/guide/le_protocole_it\303\251rateur_historique/index.html" new file mode 100644 index 0000000000..e106851141 --- /dev/null +++ "b/files/fr/web/javascript/guide/le_protocole_it\303\251rateur_historique/index.html" @@ -0,0 +1,78 @@ +--- +title: Le protocole itérateur historique +slug: Web/JavaScript/Guide/Le_protocole_itérateur_historique +tags: + - JavaScript + - Legacy Iterator +translation_of: >- + Web/JavaScript/Reference/Deprecated_and_obsolete_features/The_legacy_Iterator_protocol +--- +
{{JSSideBar("More")}}
+ +
Non-standard. Ce protocole historique était une fonctionnalité spécifique à SpiderMonkey et est supprimé à partir de Firefox 58. Pour utiliser des itérations par la suite, veuillez utiliser des boucles for..of ainsi que le protocole itérateur.
+ +

Le protocole itérateur obsolète, spécifique à Firefox

+ +

Avant la version 26, Firefox implémentait un autre protocole d'itération semblable à celui défini par ES2015.

+ +

Un objet est un itérateur historique lorsqu'il implémente une méthode next() avec la sémantique suivante et lorsqu'il renvoie une exception {{jsxref("Objets_globaux/StopIteration", "StopIteration")}} à la fin de l'itération :

+ + + + + + + + + + + + +
PropriétéValeur
next +

Une fonction sans argument qui renvoie une valeur.

+
+ +

Les différences entre le protocole historique et celui d'ES2015

+ + + +

Un exemple simple utilisant l'ancien protocole

+ +

Exemple

+ +
function créerItérateur(tableau){
+    var nextIndex = 0;
+
+    return {
+       next: function(){
+           if(nextIndex < tableau.length){
+               return tableau[nextIndex++];
+           else
+               throw new StopIteration();
+       }
+    }
+}
+
+var it = créerItérateur(['yo', 'ya']);
+
+console.log(it.next()); // 'yo'
+console.log(it.next()); // 'ya'
+try{
+    console.log(it.next());
+}
+catch(e){
+    if(e instanceof StopIteration){
+         // fin de l'itération
+    }
+}
+
+ +

Voir aussi

+ + diff --git a/files/fr/web/javascript/guide/modules/index.html b/files/fr/web/javascript/guide/modules/index.html new file mode 100644 index 0000000000..eae2c2a887 --- /dev/null +++ b/files/fr/web/javascript/guide/modules/index.html @@ -0,0 +1,432 @@ +--- +title: Les modules JavaScript +slug: Web/JavaScript/Guide/Modules +tags: + - Guide + - JavaScript + - Modules + - export + - import +translation_of: Web/JavaScript/Guide/Modules +--- +
{{jsSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Métaprogrammation")}}
+ +

Ce guide aborde l'ensemble des notions vous permettant d'utiliser la syntaxe des modules en JavaScript.

+ +

Un peu de contexte

+ +

Les programmes JavaScript ont commencé par être assez petits, réalisant des tâches isolées uniquement là où l'interactivité était nécessaire. Après plusieurs années, nous avons maintenant des applications complètes qui sont exécutées dans les navigateurs avec des codes complexes et volumineux. Des programmes JavaScript sont également exécutés dans d'autres contextes (Node.js par exemple).

+ +

Il a donc été question de fournir un mécanisme pour diviser les programmes JavaScript en plusieurs modules qu'on pourrait importer les uns dans les autres. Cette fonctionnalité était présente dans Node.js depuis longtemps et plusieurs bibliothèques et frameworks JavaScript ont permis l'utilisation de modules (CommonJS, AMD, RequireJS ou, plus récemment, Webpack et Babel).

+ +

Bonne nouvelle, les navigateurs ont également commencé à prendre en charge ces fonctionnalités nativement. C'est le sujet de ce guide.

+ +

Cette implémentation permettra aux navigateurs d'optimiser le chargement des modules, rendant le fonctionnement plus efficace qu'une bibliothèque tierce avec un traitement côté client des allers-retours sur le réseau.

+ +

Compatibilité des navigateurs

+ +

L'utilisation des modules natifs JavaScript repose sur les instructions import and export dont vous pouvez voir l'état de la compatibilité ici :

+ +

import

+ +

{{Compat("javascript.statements.import")}}

+ +

export

+ +

{{Compat("javascript.statements.export")}}

+ +

Commençons par un exemple

+ +

Pour illustrer le fonctionnement des modules, nous avons créé un ensemble d'exemples disponibles sur GitHub. Ces exemples illustrent un ensemble de modules pour créer un élément {{htmlelement("canvas")}} sur une page web puis dessiner (et afficher des informations) sur les différentes formes du canevas.

+ +

Ces opérations sont assez simples mais nous les avons choisies pour nous concentrer plutôt sur le fonctionnement des modules.

+ +
+

Note : Si vous souhaitez télécharger les exemples et les exécuter en local, vous devrez utiliser un serveur web local.

+
+ +

Structure de l'exemple

+ +

Dans notre premier exemple (cf. basic-modules), nous avons l'arborescence de fichier suivante :

+ +
index.html
+main.mjs
+modules/
+    canvas.mjs
+    square.mjs
+ +
+

Note : Tous les exemples de ce guide suivent la même structure.

+
+ +

Le répertoire dédié aux modules contient deux modules :

+ + + +
+

Note: Pour les modules JavaScript natifs, l'extension .mjs a son importance car elle permet d'importer des fichiers avec un type MIME javascript/esm (on pourra utiliser une autre extension qui fournira le type MIME application/javascript) afin d'éviter les erreurs liées à la vérification des types MIME. L'extension .mjs est notamment utile afin de distinguer plus clairement les scripts « classiques » des modules et pourra être exploitée par d'autres outils. Pour plus de détails, voir cette note de Google.

+
+ +

Exporter des fonctionnalités

+ +

Pour commencer et afin d'utiliser les fonctionnalités d'un module, on devra les exporter. Pour cela, on utilisera l'instruction export.

+ +

La méthode la plus simple consiste à placer cette instruction devant chaque valeur qu'on souhaite exporter, par exemple :

+ +
export const name = 'square';
+
+export function draw(ctx, length, x, y, color) {
+  ctx.fillStyle = color;
+  ctx.fillRect(x, y, length, length);
+
+  return {
+    length: length,
+    x: x,
+    y: y,
+    color: color
+  };
+}
+ +

Il est possible d'exporter des fonctions, des variables (qu'elles soient définies avec var, let ou const) et aussi des classes (que nous verrons par la suite). Les valeurs exportées doivent être présentes au plus haut niveau du script, il n'est pas possible d'utiliser export dans une fonction.

+ +

Une méthode plus concise consiste à exporter l'ensemble des valeurs grâce à une seule instruction située à la fin du fichier : les valeurs sont séparées par des virgules et la liste est délimitée entre accolades :

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

Importer des fonctionnalités

+ +

Lorsque des fonctionnalités sont exportées par un premier module, on peut les importer dans un script afin de les utiliser. Voici la méthode la plus simple pour ce faire :

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.mjs';
+ +

On utilise ici l'instruction import, suivi d'une liste d'identifiants séparées par des virgules et délimitée par des accolades, suivie du mot-clé from puis du chemin vers le fichier du module. Le chemin est relatif à la racine du site. Dans notre cas, pour basic-module, on écrira /js-examples/modules/basic-modules.

+ +

Ici, nous avons écrit le chemin d'une façon légèrement différente : on utilise le point (.) afin d'indiquer « l'emplacement courant », suivi du chemin vers le fichier. Cela permet d'éviter d'avoir à écrire l'intégralité du chemin à chaque fois, c'est aussi plus court et cela permet de déplacer le script et le modules sans avoir à modifier les scripts.

+ +

Ainsi :

+ +
/js-examples/modules/basic-modules/modules/square.mjs
+ +

devient :

+ +
./modules/square.mjs
+ +

Vous pouvez voir ces lignes dans main.mjs.

+ +
+

Note : Pour certains systèmes de module, on peut omettre l'extension de fichier et le point (c'est-à-dire qu'on peut écrire  '/modules/square'). Cela ne fonctionne pas pour les modules JavaScript !

+
+ +

Une fois les fonctionnalités importées dans le script, vous pouvez utiliser les valeurs dans votre script. Dans main.mjs, après les lignes d'import, on trouvera :

+ +
let myCanvas = create('myCanvas', document.body, 480, 320);
+let reportList = createReportList(myCanvas.id);
+
+let square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
+reportArea(square1.length, reportList);
+reportPerimeter(square1.length, reportList);
+
+ +

Charger le module via le document HTML

+ +

Il faut ensuite pouvoir charger le script main.mjs sur la page HTML. Pour cela, nous allons voir qu'il y a quelques différences avec le chargement d'un script « classique ».

+ +

Tout d'abord, il est nécessaire d'indiquer type="module" dans l'élément {{htmlelement("script")}} afin d'indiquer qu'on charge des modules :

+ +
<script type="module" src="main.mjs"></script>
+ +

Le script qu'on importe ici agit comme le module de plus haut niveau. Si on oublie ce type, Firefox déclenchera une erreur "SyntaxError: import declarations may only appear at top level of a module".

+ +

Les instructions import et export ne peuvent être utilisées qu'à l'intérieur de modules et pas à l'intérieur de scripts « classiques ».

+ +
+

Note : Il est aussi possible d'importer des modules dans des scripts qui sont déclarés en incise si on indique bien type="module". On pourra donc écrire <script type="module"> //code du script utilisant les modules ici </script>.

+
+ +

Différences entre les modules et les scripts « classiques »

+ + + +

Exports par défaut et exports nommés

+ +

Jusqu'à présent, nous avons utilisé des exports nommés — chaque valeur est exportée avec un nom et c'est ce nom qui est également utilisé lorsqu'on réalise l'import.

+ +

Il existe également un export par défaut — conçu pour simplifier l'export d'une fonction par module et pour faciliter l'interopérabilité avec les systèmes de module CommonJS et AMD (pour plus d'informations, voir ES6 en détails : les modules).

+ +

Prenons un exemple pour comprendre le fonctionnement des exports par défaut. Dans square.mjs, on a une fonction intitulée randomSquare() qui crée un carré avec une taille/couleur/position aléatoires. On souhaite exporter cette fonction par défaut et on écrit donc ceci à la fin du fichier :

+ +
export default randomSquare;
+ +

On notera ici l'absence d'accolades.

+ +

On aurait également pu ajouter export default devant le mot-clé function et la définir comme fonction anonyme :

+ +
export default function(ctx) {
+  ...
+}
+ +

Dans le fichier main.mjs, on importe la fonction par défaut avec cette ligne

+ +
import randomSquare from './modules/square.mjs';
+ +

On voit ici aussi l'absence d'accolade car il n'y a qu'un seul export par défaut possible par module (et ici, on sait qu'il s'agit de randomSquare). La ligne ci-avant est en fait une notation raccourcie équivalente à :

+ +
import {default as randomSquare} from './modules/square.mjs';
+ +
+

Note : Pour en savoir plus sur le renommage des objets exportés, voir ci-après {{anch("Renommage des imports et des exports")}}.

+
+ +

Gestion des conflits de nommage

+ +

Jusqu'à présent, notre exemple fonctionne. Mais que se passerait-il si nous ajoutions un module permettant de dessiner une autre forme comme un cercle ou un triangle ? Ces formes disposeraient sans doute également de fonctions telles que draw(), reportArea(), etc. Si on essaie d'importer ces fonctions avec les mêmes noms dans le module de plus haut niveau, nous allons avoir des conflits et des erreurs.

+ +

Heureusement, il existe différentes façons de résoudre ce problème.

+ +

Renommage des imports et des exports

+ +

Entre les accolades utilisées pour les instructions import et export, on peut utiliser le mot-clé as avec un autre nom afin de modifier le nom par lequel on souhaite identifier la fonctionnalité.

+ +

Ainsi, les deux fragments qui suivent permettraient d'obtenir le même résultat de façons différentes :

+ +
// dans module.mjs
+export {
+  fonction1 as nouveauNomDeFonction,
+  fonction2 as autreNouveauNomDeFonction
+};
+
+// dans main.mjs
+import { nouveauNomDeFonction, autreNouveauNomDeFonction } from './modules/module.mjs';
+ +
// dans module.mjs
+export { fonction1, fonction2 };
+
+// dans main.mjs
+import { fonction1 as nouveauNomDeFonction,
+         fonction2 as autreNouveauNomDeFonction } from './modules/module.mjs';
+ +

Prenons un exemple concret. Dans le répertoire renaming, vous verrez le même système de modules que précédemment auquel nous avons ajouté circle.mjs et triangle.mjs afin de dessiner et d'écrire des informations sur des cercles et des triangles.

+ +

Dans chaque module, on exporte les fonctionnalités avec des noms identiques : l'instruction  export utilisée est la même à chaque fin de fichier :

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

Lorsqu'on importe les valeurs dans main.mjs, si on essaie d'utiliser

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.mjs';
+import { name, draw, reportArea, reportPerimeter } from './modules/circle.mjs';
+import { name, draw, reportArea, reportPerimeter } from './modules/triangle.mjs';
+ +

Le navigateur déclenchera une erreur telle que "SyntaxError: redeclaration of import name" (Firefox).

+ +

Pour éviter ce problème, on renomme les imports afin qu'ils soient uniques :

+ +
import { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter } from './modules/square.mjs';
+
+import { name as circleName,
+         draw as drawCircle,
+         reportArea as reportCircleArea,
+         reportPerimeter as reportCirclePerimeter } from './modules/circle.mjs';
+
+import { name as triangleName,
+        draw as drawTriangle,
+        reportArea as reportTriangleArea,
+        reportPerimeter as reportTrianglePerimeter } from './modules/triangle.mjs';
+ +

On aurait pu également résoudre le problème dans les fichiers de chaque module.

+ +
// dans square.mjs
+export { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter };
+ +
// dans main.mjs
+import { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } from './modules/square.mjs';
+ +

Les deux approches fonctionnent. C'est à vous de choisir le style. Toutefois, il est souvent plus pratique d'effectuer le renommage à l'import, notamment lorsqu'on importe des fonctionnalités de modules tiers sur lesquels on n'a pas le contrôle.

+ +

Créer un objet module

+ +

La méthode précédente fonctionne mais reste « brouillonne ». Pour faire mieux, on peut importer l'ensemble des fonctionnalités de chaque module dans un objet, de la façon suivante :

+ +
import * as Module from './modules/module.mjs';
+ +

Cela récupère tous les exports disponibles depuis module.mjs et les transforme en propriétés et méthodes rattachées à l'objet Module qui fournit alors un espace de noms (namespace) :

+ +
Module.function1()
+Module.function2()
+etc.
+ +

Là encore, prenons un exemple concret avec le répertoire module-objects. Il s'agit du même exemple que précédemment mais qui a été réécrit afin de tirer parti de cette syntaxe. Dans les modules, les exports sont tous écrits ainsi :

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

En revanche, pour les imports, on les récupère ainsi :

+ +
import * as Canvas from './modules/canvas.mjs';
+
+import * as Square from './modules/square.mjs';
+import * as Circle from './modules/circle.mjs';
+import * as Triangle from './modules/triangle.mjs';
+ +

Dans chaque cas, on peut accéder aux imports comme propriétés des objets ainsi créés :

+ +
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, 'blue');
+Square.reportArea(square1.length, reportList);
+Square.reportPerimeter(square1.length, reportList);
+ +

On obtient alors un code plus lisible.

+ +

Classes et modules

+ +

Comme mentionné avant, il est possible d'importer et d'exporter des classes. Cette méthode peut aussi être utilisée afin d'éviter les conflits de nommage. Elle s'avère notamment utile lorsque vous utilisez déjà des classes pour construire vos objets (cela permet de garder une certaine cohérence dans le style).

+ +

Pour voir le résultat obtenu, vous pouvez consulter le répertoire classes du dépôt où l'ensemble a été réécrit pour tirer parti des classes ECMAScript. Ainsi, square.mjs contient désormais l'ensemble des fonctionnalités via une classe :

+ +
class Square {
+  constructor(ctx, listId, length, x, y, color) {
+    ...
+  }
+
+  draw() {
+    ...
+  }
+
+  ...
+}
+ +

Il suffit d'exporter cette classe :

+ +
export { Square };
+ +

Puis de l'importer ainsi dans main.mjs :

+ +
import { Square } from './modules/square.mjs';
+ +

Ensuite, on peut utiliser cette classe afin de dessiner le carré :

+ +
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+square1.draw();
+square1.reportArea();
+square1.reportPerimeter();
+ +

Agréger des modules

+ +

Il arrivera qu'on veuille agréger des modules entre eux. On peut avoir plusieurs niveaux de dépendances et vouloir simplifier les choses en combinant différents sous-modules en un seul module parent. Pour cela, on pourra utiliser la notation raccourcie suivante :

+ +
export * from 'x.mjs'
+export { name } from 'x.mjs'
+ +

Pour voir cela en pratique, vous pouvez consulter le répertoire module-aggregation. Dans cet exemple (construit sur le précédent qui utilise les classes), on a un module supplémentaire intitulé shapes.mjs qui agrège les fonctionnalités fournies par circle.mjs, square.mjs et triangle.mjs. Les sous-modules ont également été déplacés dans un répertoire shapes situé dans un répertoire modules. L'arborescence utilisée est donc :

+ +
modules/
+  canvas.mjs
+  shapes.mjs
+  shapes/
+    circle.mjs
+    square.mjs
+    triangle.mjs
+ +

Dans chaque sous-module, l'export aura la même forme :

+ +
export { Square };
+ +

Pour l'agrégation au sein de shapes.mjs, on écrit les lignes suivantes :

+ +
export { Square } from './shapes/square.mjs';
+export { Triangle } from './shapes/triangle.mjs';
+export { Circle } from './shapes/circle.mjs';
+ +

On récupère ainsi l'ensemble des exports de chaque module et on les rend disponibles via shapes.mjs.

+ +
+

Note : Cette notation ne permet que de rediriger les exports via le fichier. Les objets importés/exportés n'existent pas vraiment dans shapes.mjs et on ne peut donc pas écrire de code utile qui les manipule.

+
+ +

Dans le fichier main.mjs, on pourra alors remplacer :

+ +
import { Square } from './modules/square.mjs';
+import { Circle } from './modules/circle.mjs';
+import { Triangle } from './modules/triangle.mjs';
+ +

par :

+ +
import { Square, Circle, Triangle } from './modules/shapes.mjs';
+ +

Chargement dynamique de modules

+ +

Cette nouvelle fonctionnalité permet aux navigateurs de charger les modules lorsqu'ils sont nécessaires plutôt que de tout précharger en avance de phase. Cette méthode offre de nombreux avantages quant aux performances. Voyons comment cela fonctionne.

+ +

Pour utiliser cette fonctionnalité, on pourra utiliser import() comme une fonction et lui passer le chemin du module en argument. Cette fonction renverra une promesse, qui sera résolue en un module objet donnant accès aux exports.

+ +
import('./modules/monModule.mjs')
+  .then((module) => {
+    // Faire qqc avec le module.
+  });
+ +

Dans nos exemples, regardons le répertoire dynamic-module-imports, également basé sur les classes. Cette fois, on ne dessine rien au chargement de l'exemple mais on ajoute trois boutons — "Circle", "Square" et "Triangle" — qui, lorsqu'ils seront utilisés, chargeront dynamiquement les modules nécessaires et les utiliseront pour charger la forme associée.

+ +

Dans cet exemple, nous avons uniquement modifié index.html et main.js — les exports restent les mêmes.

+ +

Dans main.js, on récupère une référence à chaque bouton en utilisant document.querySelector(). Par exemple :

+ +
let squareBtn = document.querySelector('.square');
+ +

Ensuite, on attache un gestionnaire d'évènement à chaque bouton afin qu'on puisse appuyer dessus. Le module correspondant est alors chargé dynamiquement et utilisé pour dessiner la forme :

+ +
squareBtn.addEventListener('click', () => {
+  import('./modules/square.mjs').then((Module) => {
+    let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+    square1.draw();
+    square1.reportArea();
+    square1.reportPerimeter();
+  })
+});
+ +

On voit ici que, parce que la promesse renvoie un objet module à la résolution, la classe est une propriété de cet objet et qu'il faut ajouter cet espace de nom devant le constructeur exporté pour l'utiliser. Autrement dit, avec cette méthode, on doit ajouter Module. devant Square (plutôt que d'utiliser uniquement Square).

+ +

Diagnostiquer les problèmes avec les modules

+ +

Voici quelques notes pour aider à comprendre et à diagnostiquer les problèmes parfois rencontrés avec les modules. N'hésitez pas à ajouter vos conseils à cette liste si vous en avez.

+ + + +

Voir aussi

+ + + +

{{Previous("Web/JavaScript/Guide/Métaprogrammation")}}

diff --git "a/files/fr/web/javascript/guide/m\303\251taprogrammation/index.html" "b/files/fr/web/javascript/guide/m\303\251taprogrammation/index.html" new file mode 100644 index 0000000000..fcec88d12b --- /dev/null +++ "b/files/fr/web/javascript/guide/m\303\251taprogrammation/index.html" @@ -0,0 +1,278 @@ +--- +title: Métaprogrammation +slug: Web/JavaScript/Guide/Métaprogrammation +tags: + - Guide + - JavaScript + - Proxy + - Reflect +translation_of: Web/JavaScript/Guide/Meta_programming +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/iterateurs_et_generateurs","Web/JavaScript/Guide/Modules")}}
+ +

À partir d'ECMAScript 2015, JavaScript fournit les objets natifs {{jsxref("Proxy")}} et {{jsxref("Reflect")}}. Ces objets permettent d'intercepter et de définir des comportements spécifiques pour certaines opérations fondamentales du langage (par exemple la recherche d'une propriété, l'affectation, l'énumération, l'appel d'une fonction, etc.). Grâce à ces deux objets, il est possible d'interagir avec le langage lui-même (on parle alors de métaprogrammation).

+ +

Les proxies

+ +

Introduits avec ECMAScript 2015, les objets {{jsxref("Proxy")}} permettent d'intercepter certaines opérations JavaScript et de définir le comportement à avoir quand celles-ci se produisent. Par exemple, on peut intercepter l'accès à une propriété d'un objet :

+ +
var handler = {
+  get: function(cible, nom){
+    return nom in cible ? cible[nom] : 42;
+}};
+var p = new Proxy({}, handler);
+p.a = 1;
+console.log(p.a, p.b); // 1, 42
+
+ +

Ici, l'objet Proxy définit une cible (ici c'est un objet vide) et un gestionnaire (handler) qui implémente une trappe pour l'opération get. Ainsi, l'objet qui est « proxyfié » ne renverra pas undefined lorsqu'on tentera d'accéder à une propriété qui n'est pas définie, à la place le nombre 42 sera renvoyé.

+ +
+

D'autres exemples sont disponibles sur la page de l'objet {{jsxref("Proxy")}}.

+
+ +

Terminologie

+ +

Lorsqu'on utilise les proxies et leurs fonctionnalités, on utilisera les termes suivants :

+ +
+
{{jsxref("Objets_globaux/Proxy/handler","gestionnaire (handler)","","true")}}
+
L'objet qui contient les trappes.
+
trappes
+
Les méthodes qui fournissent l'accès aux propriétés. Ce concept est analogue aux trappes utilisées dans les systèmes d'exploitations.
+
cible
+
L'objet que le proxy virtualise. C'est généralement un objet utilisé en arrière-plan pour stocker les informations. Les invariants (c'est-à-dire les éléments sémantiques qui doivent rester inchangés) concernant le caractère non-extensible de l'objet ou l'aspect non-configurable des propriétés sont vérifiés par rapport à cet objet cible.
+
invariants
+
Les éléments sémantiques qui ne doivent pas être modifiés par les opérations définies dans les proxies. Si un invariant n'est pas respecté au sein d'un gestionnaire, cela provoquera une exception {{jsxref("TypeError")}}.
+
+ +

Les gestionnaires et les trappes

+ +

Le tableau suivant résume les différentes trappes disponibles pour les objets Proxy. Pour plus d'explications et de détails, voir les différents pages de la référence sur chacun de ces concepts.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Gestionnaires / TrappesOpérations interceptéesInvariants
{{jsxref("Objets_globaux/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}}{{jsxref("Object.getPrototypeOf()")}}
+ {{jsxref("Reflect.getPrototypeOf()")}}
+ {{jsxref("Object/proto", "__proto__")}}
+ {{jsxref("Object.prototype.isPrototypeOf()")}}
+ {{jsxref("Operators/instanceof", "instanceof")}}
getPrototypeOf doit renvoyer un objet ou null.
+
+ Si cible n'est pas extensible, Object.getPrototypeOf(proxy) doit renvoyer le même objet que Object.getPrototypeOf(cible).
{{jsxref("Objets_globaux/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}}{{jsxref("Object.setPrototypeOf()")}}
+ {{jsxref("Reflect.setPrototypeOf()")}}
+

Si cible n'est pas extensible, le paramètre prototype doit être la même valeur que Object.getPrototypeOf(cible).

+
{{jsxref("Objets_globaux/Proxy/handler/isExtensible", "handler.isExtensible()")}} +

{{jsxref("Object.isExtensible()")}}

+ +

{{jsxref("Reflect.isExtensible()")}}

+
+

Object.isExtensible(proxy) doit renvoyer la même valeur que Object.isExtensible(target).

+
{{jsxref("Objets_globaux/Proxy/handler/preventExtensions", "handler.preventExtensions()")}} +

{{jsxref("Object.preventExtensions()")}}

+ +

{{jsxref("Reflect.preventExtensions()")}}

+
+

Object.preventExtensions(proxy) ne renvoie true que si Object.isExtensible(proxy) vaut false.

+
{{jsxref("Objets_globaux/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}} +

{{jsxref("Object.getOwnPropertyDescriptor()")}}

+ +

{{jsxref("Reflect.getOwnPropertyDescriptor()")}}

+
+

getOwnPropertyDescriptor doit renvoyer un objet ou undefined.

+ +

Une propriété ne peut pas être vue comme non-existante si elle existe comme une propriété propre non-configurable de l'objet cible.

+ +

Une propriété ne peut pas être vue comme non-existante si elle existe comme une propriété propre de la cible et que l'objet cible n'est pas extensible.

+ +

Une propriété ne peut pas être vue comme existante si elle n'existe pas comme une propriété propre de l'objet cible et que l'objet cible n'est pas extensible.

+ +

Une propriété ne peut pas être vue comme non-configurable si elle n'existe pas comme une propriété propre de l'objet cible ou si elle existe comme une propriété configurable propre de l'objet cible.

+ +

Le résultat de Object.getOwnPropertyDescriptor(cible) peut être appliqué à la cible en utilisant Object.defineProperty sans que cela ne lève d'exception.

+
{{jsxref("Objets_globaux/Proxy/handler/defineProperty", "handler.defineProperty()")}} +

{{jsxref("Object.defineProperty()")}}

+ +

{{jsxref("Reflect.defineProperty()")}}

+
+

Une propriété ne peut pas être ajoutée si l'objet cible n'est pas extensible.

+ +

Une propriété ne peut pas être ajoutée ou être modifiée afin d'être non-configurable si elle n'existe pas comme une propriété propre de l'objet cible et qu'elle n'est pas non-configurable.

+ +

Une propriété peut ne pas être non-configurable si une propriété correspondante configurable existe sur l'objet cible.

+ +

Si une propriété possède une propriété correspondante sur l'objet cible, Object.defineProperty(cible, prop, descripteur) ne doit pas renvoyer d'exception.

+ +

En mode strict, si la valeur de retour de defineProperty est false, cela entraînera une exception {{jsxref("TypeError")}} exception.

+
{{jsxref("Objets_globaux/Proxy/handler/has", "handler.has()")}} +

Requête d'une propriété : toto in proxy

+ +

Requête d'une propriété héritée : toto in Object.create(proxy)

+ +

{{jsxref("Reflect.has()")}}

+
+

Une propriété ne peut pas être vue comme non-existante si elle existe comme propriété propre non-configurable de l'objet cible.

+ +

Une propriété ne peut pas être vue comme non-existante si elle existe comme propriété propre de l'objet cible et que l'objet cible n'est pas extensible.

+
{{jsxref("Objets_globaux/Proxy/handler/get", "handler.get()")}} +

Accès à une propriété : proxy[toto] et proxy.truc

+ +

Accès à une propriété héritée : Object.create(proxy)[toto]

+ +

{{jsxref("Reflect.get()")}}

+
+

La valeur rapportée pour la propriété doit être la même que la valeur de la propriété correspondante sur l'objet cible si celle-ci est une propriété de donnée non accessible en écriture et non-configurable..

+ +

La valeur rapportée pour une propriété doit être undefined si la propriété correspondante de l'objet cible est une propriété d'accesseur dont l'attribut [[Get]] vaut undefined.

+
{{jsxref("Objets_globaux/Proxy/handler/set", "handler.set()")}} +

Affection d'une propriété : proxy[toto] = truc et proxy.toto = truc
+
+ Affectation d'une propriété héritée : Object.create(proxy)[toto] = truc
+
+ {{jsxref("Reflect.set()")}}

+
+

Il est impossible de modifier la valeur d'une propriété pour que celle-ci soit différente de la valeur de la propriété correspondante de l'objet cible si la propriété de l'objet cible est une propriété de donnée qui n'est pas accessible en écriture et qui n'est pas configurable.

+ +

Il est impossible de modifier la valeur d'une propriété si la propriété correspondante de l'objet cible est une propriété d'accesseur non-configurable dont l'attribut [[Set]] vaut undefined.

+ +

En mode strict, si le gestionnaire pour set renvoie false, cela provoquera une exception {{jsxref("TypeError")}}.

+
{{jsxref("Objets_globaux/Proxy/handler/deleteProperty", "handler.deleteProperty()")}} +

Suppression d'une propriété : delete proxy[toto] et delete proxy.toto
+
+ {{jsxref("Reflect.deleteProperty()")}}

+
Une propriété ne peut pas être supprimée si elle existe comme une propriété propre non-configurable de l'objet cible.
{{jsxref("Objets_globaux/Proxy/handler/enumerate", "handler.enumerate()")}} +

Lister les propriétés avec for...in : for (var nom in proxy) {...}
+
+ {{jsxref("Reflect.enumerate()")}}

+
La méthode enumerate doit renvoyer un objet.
{{jsxref("Objets_globaux/Proxy/handler/ownKeys", "handler.ownKeys()")}} +

{{jsxref("Object.getOwnPropertyNames()")}}
+ {{jsxref("Object.getOwnPropertySymbols()")}}
+ {{jsxref("Object.keys()")}}
+ {{jsxref("Reflect.ownKeys()")}}

+
+

Le résultat de ownKeys est une liste.
+
+ Le type de chaque élément de la liste est soit une {{jsxref("String")}} soit un  {{jsxref("Symbol")}}.
+
+ La liste résultatnte doit contenir les clés de toutes les propriétés non-configurables de l'objet cible.
+
+ Si l'objet cible n'est pas extensible, la liste résultante doit contenir toutes les clés des propriétés propres de l'objet cibles et aucune autre valeur.

+
{{jsxref("Objets_globaux/Proxy/handler/apply", "handler.apply()")}} +

proxy(..args)
+
+ {{jsxref("Function.prototype.apply()")}} and {{jsxref("Function.prototype.call()")}}
+
+ {{jsxref("Reflect.apply()")}}

+
Il n'y a pas d'invariant pour la méthode handler.apply.
{{jsxref("Objets_globaux/Proxy/handler/construct", "handler.construct()")}} +

new proxy(...args)
+ {{jsxref("Reflect.construct()")}}

+
Le résultat doit être un Objet.
+ +

Proxies révocables

+ +

La méthode {{jsxref("Proxy.revocable()")}} est utilisée pour créer un objet Proxy qui puisse être révoqué. Cela signifie que que le proxy pourra être révoqué avec la fonction revoke et arrêtera le proxy. Après cet arrêt, toute opération sur le proxy entraînera une exception {{jsxref("TypeError")}}.

+ +
var revocable = Proxy.revocable({}, {
+  get: function(cible, nom) {
+    return "[[" + nom + "]]";
+  }
+});
+var proxy = revocable.proxy;
+console.log(proxy.toto); // "[[toto]]"
+
+revocable.revoke();
+
+console.log(proxy.toto); // déclenche une TypeError
+proxy.toto = 1;          // une TypeError encore
+delete proxy.toto;       // toujours une TypeError
+typeof proxy             // "object", typeof ne déclenche aucune trappe
+ +

Réflexion

+ +

{{jsxref("Reflect")}} est un objet natif qui fournit des méthodes pour les opérations JavaScript qui peuvent être interceptées. Ces méthodes sont les mêmes que celles gérées par les {{jsxref("Objets_globaux/Proxy/handler","gestionnaires de proxy","","true")}}. Reflect n'est pas un constructeur et ne peut pas être utilisé comme une fonction !

+ +

Reflect aide à transférer les opérations par défaut depuis le gestionnaire vers la cible.

+ +

Par exemple, avec {{jsxref("Reflect.has()")}}, on obtient le comportement de l'opérateur in sous forme d'une fonction :

+ +
Reflect.has(Object, "assign"); // true
+
+ +

{{PreviousNext("Web/JavaScript/Guide/iterateurs_et_generateurs","Web/JavaScript/Guide/Modules")}}

diff --git a/files/fr/web/javascript/guide/nombres_et_dates/index.html b/files/fr/web/javascript/guide/nombres_et_dates/index.html new file mode 100644 index 0000000000..a7debdc697 --- /dev/null +++ b/files/fr/web/javascript/guide/nombres_et_dates/index.html @@ -0,0 +1,387 @@ +--- +title: Nombres et dates +slug: Web/JavaScript/Guide/Nombres_et_dates +tags: + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Numbers_and_dates +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_et_Op%C3%A9rateurs", "Web/JavaScript/Guide/Formatage_du_texte")}}
+ +

Ce chapitre illustre le fonctionnement des nombres et des dates en JavaScript grâce aux concepts, objets et fonctions utilisables avec ce langage. Cela inclut notamment l'écriture de nombre selon différentes bases (décimale, binaire, hexadécimale) et l'utilisation de l'objet global {{jsxref("Math")}}.

+ +

Nombres

+ +

Les nombres en JavaScript sont implémentés comme des nombres sur 64 bits à précision double selon le format IEEE-754 qui est un standard pour la représentation des nombres flottants et qui permet d'avoir jusqu'à 16 chiffres significatifs. Le type numérique possède également trois valeurs spéciales symboliques : +{{jsxref("Infinity")}}, -{{jsxref("Infinity")}} et {{jsxref("NaN")}} (pour désigner une valeur qui n'est pas un nombre).

+ +

Le format IEEE-754 permet de représenter des valeurs entre ±2−1022 et ±2+1023, ce qui correspond à des valeurs entre ±10−308 et ±10+308 avec une précision sur 53 bits. Les nombres entiers compris sur l'intervalle ±253 − 1 peuvent être représentés exactement.

+ +

Le type {{jsxref("BigInt")}} est une addition récente à JavaScript qui permet de représenter de grands entiers. Toutefois, il n'est pas possible de mélanger les BigInt et les nombres ({{jsxref("Number")}}) dans les mêmes opérations et on ne peut pas utiliser l'objet {{jsxref("Math")}} avec les valeurs BigInt.

+ +

Voir également les types de données et structures JavaScript pour l'articulation des types primitifs en JavaScript.

+ +

Il est possible d'utiliser quatre types de littéraux numériques : décimal, binaire, octal et hexadécimal.

+ +

Les nombres décimaux

+ +
1234567980;
+42;
+
+// Attention à l'utilisation des zéros
+// en début de nombre
+
+0888; // 888 analysé en base décimale
+0777; // en mode non-strict, analysé en base octale,
+      // ce qui correspond
+      // à 511 en base décimale
+
+ +

On voit ici que les littéraux numériques qui commencent par un zéro (0) et contiennent un chiffre strictement inférieur à 8 après ce 0 sont analysés comme étant exprimés en base octale.

+ +

Les nombres binaires

+ +

Pour utiliser des nombres binaires, on utilise un littéral qui commence par un 0 suivi d'un b minuscule ou majuscule (0b ou 0B). Si les chiffres qui suivent ce préfixe ne sont pas des 0 ou des 1, une exception {{jsxref("SyntaxError")}} sera levée.

+ +
var FLT_BITSIGNE = 0b10000000000000000000000000000000; // 2147483648
+var FLT_EXPOSANT = 0b01111111100000000000000000000000; // 2139095040
+var FLT_MANTISSE = 0B00000000011111111111111111111111; // 8388607
+
+ +

Les nombres octaux

+ +

Pour utiliser des nombres en base octale, on utilisera un préfixe avec un 0. Si les nombres qui suivent ce 0 ne sont pas compris entre 0 et 7 (au sens strict), le nombre sera interprété comme un nombre décimal.

+ +
var n = 0755; // 493 en base 10
+var m = 0644; // 420 en base 10
+
+ +

En mode strict, ECMAScript 5 interdit cette syntaxe octale. Cette syntaxe ne fait pas partie d'ECMAScript 5 mais est supportée par la majorité des navigateurs. Avec ECMAScript 2015 (ES6), il est possible de représenter un nombre en notation octale grâce au préfixe "0o" :

+ +
var a = 0o10; // Notation octale pour ES2015
+ +

Les nombres hexadécimaux

+ +

Pour utiliser des nombres exprimés en base hexadécimale, on utilisera un préfixe avec un zéro suivi d'un x majuscule ou minuscule (0x ou 0X). Si les chiffres qui suivent ce préfixe ne sont pas 0123456789ABCDEF, cela provoquera une exception {{jsxref("SyntaxError")}}.

+ +
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
+0x123456789ABCDEF   // 81985529216486900
+0XA                 // 10
+
+ +

Notation scientifique

+ +
1E3   // 100
+2e6   // 2000000
+0.1e2 // 10
+
+ +

L'objet Number

+ +

L'objet {{jsxref("Number")}} possède certaines propriétés représentant les constantes numériques telles que : la valeur maximale représentable en JavaScript, une valeur spéciale pour dire que la valeur numérique n'est pas un nombre et l'infini. Ces valeurs ne peuvent pas être modifiées, on pourra les utiliser de la façon suivante :

+ +
var plusGrandNombre = Number.MAX_VALUE;
+var plusPetitNombre = Number.MIN_VALUE;
+var infini = Number.POSITIVE_INFINITY;
+var infiniNégatif = Number.NEGATIVE_INFINITY;
+var pasUnNombre = Number.NaN;
+
+ +

On utilisera toujours ces valeurs directement avec l'objet natif Number (et non pas avec les propriétés d'une instance d'un objet Number qu'on aurait créé).

+ +

Le tableau qui suit liste certaines des propriétés de Number.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Propriétés de Number
PropriétéDescription
{{jsxref("Number.MAX_VALUE")}}Le plus grand nombre qu'on peut représenter en JavaScript (±1.7976931348623157e+308).
{{jsxref("Number.MIN_VALUE")}}Le plus petit nombre qu'on peut représenter en JavaScript (±5e-324).
{{jsxref("Number.NaN")}}Une valeur spéciale signifiant que la valeur n'est pas un nombre.
{{jsxref("Number.NEGATIVE_INFINITY")}}L'infini négatif, renvoyé lorsqu'on dépasse la valeur minimale.
{{jsxref("Number.POSITIVE_INFINITY")}}L'infini positif, renvoyé lorsqu'on dépasse la valeur maximale.
{{jsxref("Number.EPSILON")}}La différence entre 1 et la première valeur supérieure à 1 qui puisse être représentée comme {{jsxref("Number")}}. (2.220446049250313e-16)
{{jsxref("Number.MIN_SAFE_INTEGER")}}Le plus petit entier qu'on puisse représenter en JavaScript. (−253 + 1 ou −9007199254740991)
{{jsxref("Number.MAX_SAFE_INTEGER")}} +

L'entier le plus grand qu'on puisse représenter en JavaScript (+253 − 1 ou +9007199254740991)

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Méthodes de Number
MéthodeDescription
{{jsxref("Number.parseFloat()")}}Analyse un argument qui est une chaîne de caractères et renvoie un nombre décimal. Cette méthode est équivalente à la fonction {{jsxref("parseFloat", "parseFloat()")}}.
{{jsxref("Number.parseInt()")}}Analyse un argument qui est une chaîne de caractères et renvoie un entier exprimé dans une base donnée. Cette méthode est équivalente à la fonction {{jsxref("parseInt", "parseInt()")}}.
{{jsxref("Number.isFinite()")}}Détermine si la valeur passée en argument est un nombre fini.
{{jsxref("Number.isInteger()")}}Détermine si la valeur passée en argument est un nombre entier.
{{jsxref("Number.isNaN()")}}Détermine si la valeur passée en argument est {{jsxref("NaN")}}. Cette version est plus robuste que la fonction globale {{jsxref("Objets_globaux/isNaN", "isNaN()")}}.
{{jsxref("Number.isSafeInteger()")}}Détermine si la valeur fournie est un nombre qu'il est possible de représenter comme un entier sans perdre d'information.
+ +

Le prototype de Number fournit certaines méthodes pour exprimer les valeurs représentées par les objets Number dans différents formats. Le tableau suivant liste certaines de ces méthodes de Number.prototype.

+ + + + + + + + + + + + + + + + + + + + + + + +
Méthodes of Number.prototype
MéthodeDescription
{{jsxref("Number.toExponential", "toExponential()")}}Renvoie une chaîne de caractères représentant le nombre en notation exponentielle.
{{jsxref("Number.toFixed", "toFixed()")}}Renvoie une chaîne de caractères représentant le nombre en notation à point fixe.
{{jsxref("Number.toPrecision", "toPrecision()")}}Renvoie une chaîne de caractères représentant le nombre en notation à point fixe avec une précision donnée.
+ +

L'objet Math

+ +

L'objet natif {{jsxref("Math")}} possède des propriétés et des méthodes statiques pour représenter des constantes et des fonctions mathématiques. Ainsi, la propriété PI de l'objet Math représente la valeur de la constante π\pi (3.141...), on peut l'utiliser dans les applications avec :

+ +
Math.PI
+
+ +

De la même façon, les fonctions mathématiques usuelles sont des méthodes de Math. On retrouve par exemple les fonctions trigonométriques, logarithmiques et exponentielles ainsi que d'autres fonctions. Si on souhaite utiliser la fonction sinus, on pourra écrire :

+ +
Math.sin(1.56)
+
+ +
+

Note : Les méthodes trigonométriques de Math prennent des arguments exprimés en radians.

+
+ +

Le tableau suivant liste les méthodes de l'objet Math.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Méthodes de Math
MéthodeDescription
{{jsxref("Math.abs", "abs()")}}Valeur absolue
{{jsxref("Math.sin", "sin()")}}, {{jsxref("Math.cos", "cos()")}}, {{jsxref("Math.tan", "tan()")}}Fonctions trigonométriques standards (les arguments sont exprimés en radians)
{{jsxref("Math.asin", "asin()")}}, {{jsxref("Math.acos", "acos()")}}, {{jsxref("Math.atan", "atan()")}}, {{jsxref("Math.atan2", "atan2()")}}Fonctions trigonométriques inverses (les valeurs renvoyées sont exprimées en radians)
{{jsxref("Math.sinh", "sinh()")}}, {{jsxref("Math.cosh", "cosh()")}}, {{jsxref("Math.tanh", "tanh()")}}Fonctions trigonométriques hyperboliques (les arguments sont exprimés en radians)
{{jsxref("Math.asinh", "asinh()")}}, {{jsxref("Math.acosh", "acosh()")}}, {{jsxref("Math.atanh", "atanh()")}}Fonctions trigonométriques hyperboliques inverses (les valeurs renvoyées sont exprimées en radians).
{{jsxref("Math.pow", "pow()")}}, {{jsxref("Math.exp", "exp()")}}, {{jsxref("Math.expm1", "expm1()")}}, {{jsxref("Math.log10", "log10()")}}, {{jsxref("Math.log1p", "log1p()")}}, {{jsxref("Math.log2", "log2()")}}Fonctions exponentielles et logarithmiques
{{jsxref("Math.floor", "floor()")}}, {{jsxref("Math.ceil", "ceil()")}}Renvoie le plus petit/grand entier inférieur/supérieur ou égal à l'argument donné
{{jsxref("Math.min", "min()")}}, {{jsxref("Math.max", "max()")}}Renvoie le plus petit (resp. grand) nombre d'une liste de nombres séparés par des virgules
{{jsxref("Math.random", "random()")}}Renvoie un nombre aléatoire compris entre 0 et 1
{{jsxref("Math.round", "round()")}}, {{jsxref("Math.fround", "fround()")}}, {{jsxref("Math.trunc", "trunc()")}},Fonctions d'arrondis et de troncature
{{jsxref("Math.sqrt", "sqrt()")}}, {{jsxref("Math.cbrt", "cbrt()")}}, {{jsxref("Math.hypot", "hypot()")}}Racine carrée, cubique et racine carrée de la somme des carrés des arguments
{{jsxref("Math.sign", "sign()")}}Renvoie le signe d'un nombre et indique si la valeur est négative, positive ou nulle
{{jsxref("Math.clz32", "clz32()")}},
+ {{jsxref("Math.imul", "imul()")}}
Le nombre de zéros qui commencent un nombre sur 32 bits en représentation binaire.
+ La résultat de la multiplication de deux arguments sur 32 bits effectuée comme en C.
+ +

À la différence des autres objets, on ne crée pas d'objet de type Math. Ses propriétés sont statiques, on les appelle donc toujours depuis l'objet Math.

+ +

L'objet Date

+ +

JavaScript ne possède pas de type primitif pour représenter des dates. Cependant l'objet {{jsxref("Date")}} et ses méthodes permettent de manipuler des dates et des heures au sein d'une application. L'objet Date possède de nombreuses méthodes pour définir, modifier, obtenir des dates. Il ne possède pas de propriétés.

+ +

JavaScript gère les dates de façon similaire à Java. Les deux langages possèdent de nombreuses méthodes en commun et les deux langages stockent les dates selon les nombres de millisecondes écoulées depuis le premier janvier 1970 à 00h00:00.

+ +

L'objet Date permet de représenter des dates allant de -100 000 000 jours jusqu'à +100 000 000 jours par rapport au premier janvier 1970 UTC.

+ +

Pour créer un objet Date, on utilisera la syntaxe suivante :

+ +
var monObjetDate = new Date([paramètres]);
+
+ +

avec monObjetDate étant le nom de l'objet à créer, cela peut être un nouvel objet ou une propriété d'un objet existant.

+ +

Lorsqu'on appelle Date sans le mot-clé new, cela renvoie la date fournie sous la forme d'une chaîne de caractères.

+ +

Les paramètres qui peuvent être utilisés sont :

+ + + +

Méthodes de l'objet Date

+ +

Les méthodes de l'objet Date se répartissent en différentes catégories :

+ + + +

Avec les accesseurs et les mutateurs, il est possible d'obtenir ou de modifier séparément les secondes, les minutes, les heures, le jour du mois ou de la semaine, le mois et l'année. Il existe une méthode getDay qui renvoie le jour de la semaine mais il n'existe pas de méthode réciproque setDay car le jour de la semaine est automatiquement déterminé. Ces méthodes utilisent des entiers pour représenter les valeurs utilisées :

+ + + +

Ainsi, si on définit la date suivante :

+ +
var noël95 = new Date("December 25, 1995");
+
+ +

noël95.getMonth() renverra 11, et noël95.getFullYear() renverra 1995.

+ +

Les méthodes getTime et setTime peuvent être utiles pour comparer des dates entre elles. La méthode getTime renvoie le nombre de millisecondes écoulées depuis le premier janvier 1970 à 00:00:00 pour l'objet Date.

+ +

Par exemple, les instructions suivantes affichent le nombre de jours qui restent pour l'année courante :

+ +
var aujourdhui = new Date();
+// On définit le jour et le mois
+var finAnnée = new Date(1995, 11, 31, 23, 59, 59, 999);
+// On définit l'année avec l'année courante
+finAnnée.setFullYear(aujourdhui.getFullYear());
+// On calcule le nombre de millisecondes par jour
+var msParJour = 24 * 60 * 60 * 1000;
+
+// On renvoie le nombre de jours restants dans l'année
+var joursRestants = (finAnnée.getTime() - today.getTime()) / msPerDay;
+joursRestants = Math.round(joursRestants);
+ +

Cet exemple crée un objet Date nommé aujourdhui qui contient la date du jour. On crée ensuite un objet Date nommé finAnnée pour lequel on définit ensuite l'année avec l'année courante. Après, on calcule le nombre de millisecondes qui s'écoulent dans une journée. Enfin, on calcule le nombre de jours entre aujourdhui et finAnnée en utilisant getTime puis on arrondit le tout pour avoir un nombre de jours.

+ +

La méthode parse est utile lorsqu'on souhaite affecter des valeurs temporelles à partir de chaînes de caractères. Par exemple, dans le code qui suit, on utilise les méthodes parse et setTime pour affecter la valeur d'une date à un objet IPOdate :

+ +
var IPOdate = new Date();
+IPOdate.setTime(Date.parse("Aug 9, 1995"));
+
+ +

Exemple d'utilisation de l'objet Date

+ +

Dans l'exemple qui suit, la fonction JSClock() renvoie le temps au format d'une horloge numérique représentant les heures sur 12 heures :

+ +
function JSClock() {
+  var temps = new Date();
+  var heures = temps.getHours();
+  var minutes = temps.getMinutes();
+  var secondes = temps.getSeconds();
+  var calc = "" + (heures > 12) ? heures - 12 : heures);
+  if (heures == 0)
+    calc = "12";
+  calc += ((minutes < 10) ? ":0" : ":") + minutes;
+  calc += ((secondes < 10) ? ":0" : ":") + secondes;
+  calc += (heures >= 12) ? " P.M." : " A.M.";
+  return calc;
+}
+
+ +

Pour commencer, la fonction JSClock crée un objet Date appelé temps qui représente la date et l'heure à l'instant où la fonction est exécutée. Ensuite, les méthodes getHours, getMinutes, et getSeconds sont appelées afin d'affecter les valeurs correspondantes à heures, minutes, et secondes.

+ +

Les quatre instructions suivantes permettent de construire une chaîne de caractères à partir de la valeur temporelle. La première instruction crée une variable calc et lui affecte une valeur avec une expression conditionnelle : si heures est supérieure à 12, on affichera (heures - 12), sinon on affichera l'heure sauf si c'est 0 auquel cas on affichera 12.

+ +

L'instruction qui suit concatène la valeur de minutes à calc. Si la valeur de minutes est inférieure à 10, l'expression conditionnelle ajoutera une chaîne avec un zéro pour que la valeur soit affichée avec deux chiffres. De la même façon, l'instruction qui suit concatène la valeur de calc avec les secondes.

+ +

Enfin, une expression conditionnelle est utilisée pour ajouter "P.M." à calc si heures vaut 12 ou plus, sinon ce sera la chaîne "A.M." qui sera ajoutée à la fin de calc.

+ +

{{PreviousNext("Web/JavaScript/Guide/Expressions_et_Op%C3%A9rateurs", "Web/JavaScript/Guide/Formatage_du_texte")}}

diff --git "a/files/fr/web/javascript/guide/objets_\303\251l\303\251mentaires_javascript/index.html" "b/files/fr/web/javascript/guide/objets_\303\251l\303\251mentaires_javascript/index.html" new file mode 100644 index 0000000000..cba256e851 --- /dev/null +++ "b/files/fr/web/javascript/guide/objets_\303\251l\303\251mentaires_javascript/index.html" @@ -0,0 +1,898 @@ +--- +title: Objets élémentaires JavaScript +slug: Web/JavaScript/Guide/Objets_élémentaires_JavaScript +tags: + - Guide + - JavaScript + - Objets JavaScript +translation_of: Web/JavaScript/Guide +--- +

{{jsSidebar("JavaScript Guide")}}

+ +

Dans ce chapitre nous verrons les différents objets élémentaires qui existent en JavaScript : Array, Boolean, Date, Function, Math, Number, RegExp, et String.

+ +

Les tableaux : objet Array

+ +

JavaScript ne possède pas type primitif pour les tableaux. En revanche, il est possible d'utiliser l'objet natif Array ainsi que ses méthodes pour manipuler des tableaux. L'objet Array possède différentes méthodes pour manipuler les tableaux : fusion, inverse, tri... Il possède une propriété permettant de déterminer la longueur du tableau et d'autres propriétés qu'on peut utiliser avec les expressions rationnelles.

+ +

Un tableau est un ensemble ordonné de valeurs auxquelles on peut faire référence via un nom et un indice. Si par exemple on utilise un tableau reg qui contient un registre de noms indicés (autrement dit dont la position dans le tableau est déterminée) par un identifiant : on aurait reg[1] pour le premier nom, reg[2] pour le second et ainsi de suite/

+ +

Créer un tableau :

+ +

Les instructions suivantes permettent de créer des objets Array équivalents :

+ +
+
var arr = new Array(element0, element1, ..., elementN);
+var arr = Array(element0, element1, ..., elementN);
+var arr = [element0, element1, ..., elementN];
+
+
+ +

element0, element1, ..., elementN est la liste des valeurs des éléments du tableau. Quand ces valeurs sont fournies, les éléments du tableau sont initialisés avec ses valeurs. La propriété length vaudra alors le nombre d'arguments.

+ +

La dernière syntaxe, utilisant des crochets, est appelée « littéral de tableau » ou « initialisateur de tableau ». C'est la forme la plus courte pour créer un tableau et c'est cette forme qui est souvent préférée. Voir la page Littéraux de tableaux pour plus de détails.

+ +

Lorsqu'on souhaite créer un tableau de longueur non nulle mais qui ne contient aucun élément, les syntaxes suivantes peuvent être utilisées :

+ +
var arr = new Array(longueurTabl);
+var arr = Array(longueurTabl);
+
+// Ces instructions ont le même effet
+var arr = [];
+arr.length = longueurTabl;
+
+ +

Dans le code ci-dessus, longueurTabl doit être du type Number. Si ce n'est pas le cas, un tableau avec une seule valeur, celle fournie, longueurTabl, sera créé. Si on appelle arr.length, on aura bien longueurTabl, en revanche le tableau ne contiendra que des éléments vides (indéfinis). Si on utilise une boucle for...in sur le tableau, aucun des éléments du tableau ne sera renvoyé.

+ +

En plus de définir une nouvelle variable en lui assignant un tableau, on peut également assigner les tableaux à une propriété d'un nouvel objet ou d'un objet existant :

+ +
var obj = {};
+// ...
+obj.prop = [element0, element1, ..., elementN];
+
+// OU
+var obj = {prop: [element0, element1, ...., elementN]}
+
+ +

Si on souhaite initialiser un tableau avec un seul élément qui est un nombre, on doit utiliser la syntaxe avec crochets. En effet, si on utilise le constructeur Array() auquel on passe un seul argument numérique, celui-ci sera interprété comme longueurTabl, et non pas comme le seul élément du tableau.

+ +
var arr = [42];
+var arr = Array(42); // Crée un tableau sans élément mais de longueur 42
+
+// L'instruction ci-avant est équivalente à
+var arr = [];
+arr.length = 42;
+
+
+ +

Si on appelle le constructeur Array() avec un argument qui n'est pas un nombre entier (dont la partie décimale est non nulle), on obtiendra une erreur RangeError. Voici un exemple :

+ +
var arr = Array(9.3);  // RangeError: Invalid array length
+
+ +

Si on souhaite créer des tableaux d'un seul élément (peu importe le type), il est plus adapté d'utiliser des littéraux de tableaux ou de créer un tableau vide puis d'y ajouter la valeur.

+ +

Remplir un tableau

+ +

Il est possible de remplir un tableau en affectant des valeurs à ses différents éléments :

+ +
var reg = [];
+reg[0] = "Casey Jones";
+reg[1] = "Phil Lesh";
+reg[2] = "August West";
+
+ +

Note : Si on utilise les crochets et un nombre décimal non entier, une propriété sera créée pour l'objet mais cela ne créera pas un élément du tableau.

+ +
 var arr = [];
+arr[3.4] = "Oranges";
+console.log(arr.length);                // 0
+console.log(arr.hasOwnProperty(3.4));   // true
+
+ +

On peut également remplir un tableau à la création :

+ +
var monTableau = new Array("Hello", maVar, 3.14159);
+var monTableau = ["Mangue", "Pomme", "Orange"]
+
+ +

Faire référence aux éléments d'un tableau

+ +

Il est possible de faire référence aux élément d'un tableau en utilisant leur indice dans ce tableau. Ainsi, si on définit le tableau suivant :

+ +
var monTableau = ["Vent", "Eau", "Feu"];
+
+ +

On peut faire référence au premier élément du tableau en utilisant monTableau[0] et au second élément en utilisant monTableau[1]. Les indices des éléments d'un tableau commencent à zéro.

+ +

Note : L'opérateur du tableau (les crochets) est aussi utilisé pour accéder aux propriétés du tableau (en effet les tableaux sont des objets en JavaScript, et on peut donc utiliser leurs propriétés). Par exemple :

+ +
 var tabl = ["un", "deux", "trois"];
+tabl[2];  // trois
+tabl["length"];  // 3
+
+ +

La propriété length

+ +

En termes d'implémentation, les éléments d'un tableau sont en fait stockés comme des propriétés de l'objet et l'indice de l'élément est le nom de la propriété. La propriété length est spéciale : elle renvoie toujours l'indice du dernier élément plus 1. Attention : les indices d'un tableau, en JavaScript, commencent à 0 et pas à 1.

+ +
var chats = [];
+chats[30] = ['Nyan'];
+print(chats.length); // 31
+
+ +

Il est également possible d'affecter une valeur à la propriété length. Si on lui assigne une valeur inférieure au nombre d'éléments du tableau : le tableau sera tronqué. Si on lui affecte la valeur 0, le tableau sera entièrement vidé.

+ +
var chats = ['Marie', 'Toulouse', 'Berlioz'];
+console.log(chats.length); // 3
+
+chats.length = 2;
+console.log(chats); // affiche "Marie,Toulouse" - Berlioz a été retiré
+
+chats.length = 0;
+console.log(chats); // Rien n'est affiché : tableau vide
+
+chats.length = 3;
+console.log(cats); // [undefined, undefined, undefined]
+
+ +

Effectuer des boucles sur des tableaux

+ +

On sera souvent amené à faire des boucles sur les valeurs d'un tableau pour répéter un traitement sur chacune d'elle. La façon la plus simple de faire des boucles est la suivante :

+ +
var couleurs = ['rouge', 'vert', 'bleu'];
+for (var i = 0; i < couleurs.length; i++) {
+  console.log(couleurs[i]);
+}
+
+ +

Si on est certain qu'aucun des éléments du tableau ne pourra être évalué à false. Si par exemple le tableau est constitué d'éléments du DOM, on peut utiliser la syntaxe suivante, plus efficace :

+ +
var divs = document.getElementsByTagName('div');
+for (var i = 0, div; div = divs[i]; i++) {
+  /* Effectuer un traitement sur les div */
+}
+
+ +

En faisant cela, on évite de répéter le test qui consiste à vérifier la longueur du tableau et on s'assure que la variable div est réassignée à chaque passage dans la boucle.

+ +

La méthode forEach(), introduite avec JavaScript 1.6, permet de boucler sur un tableau d'une autre façon :

+ +
var couleurs = ['rouge', 'vert', 'bleu'];
+couleurs.forEach(function(couleur) {
+  console.log(couleur);
+});
+
+ +

La fonction, passée en argument de la méthode forEach est exécutée pour chaque élément du tableau (qui sera passé en argument de cette fonction). Les éléments du tableau non assignés ne sont pas traités.

+ +

Les éléments du tableau qui n'ont pas été définis lors de la création du tableau ne sont pas utilisés avec forEach, en revanche lorsque undefined a été explicitement assigné à un élément du tableau, il est pris en compte :

+ +
var array = ['premier', 'second', , 'quatrième'];
+
+// la boucle ci-dessous renvoie ['premier', 'second', 'quatrième'];
+array.forEach(function(element) {
+  console.log(element);
+})
+
+if(array[2] === undefined) { console.log('array[2] vaut undefined'); } // true
+
+var array = ['premier', 'second', undefined, 'quatrième'];
+
+//la boucle ci-dessous renvoie ['premier', 'second', undefined, 'quatrième'];
+array.forEach(function(element) {
+  console.log(element);
+})
+ +

Les éléments d'un tableau étant stockés comme des propriétés d'un tableau, il n'est pas conseillé d'utiliser de boucle for...in pour traiter les tableaux car on traitera les éléments du tableau ainsi que toutes les propriétés énumérables.

+ +

Méthodes de l'objet Array

+ +

L'objet Array possède les méthodes suivantes :

+ + + +

Du code compatible avec les anciens navigateurs, pour remplacer ces fonctions, est disponible sur les pages qui concernent ces fonctions. Le support des navigateurs pour ces fonctions est détaillé ici (en anglais).

+ + + +

Les méthodes ci-dessus utilisent des fonctions de rappel (callback) et sont appelées méthodes itératives. En effet, d'une certaine façon, elles bouclent sur le tableau. Chacune de ces méthodes possède un argument facultatif thisObject. Si cet argument est utilisé, il représentera le contexte utilisé pour le mot-clé this utilisé dans la fonction de rappel. S'il n'est pas utilisé et que la fonction est appelée en dehors d'un contexte objet donné this fera référence à l'objet global (window). Pour plus d'informations, voir la page sur this.

+ +

En réalité, la fonction de rappel est utilisé avec trois arguments. Le premier est la valeur de l'élément, le deuxième est l'indice de l'élément et le troisième est la référence au tableau. Étant donné que JavaScript ignore les arguments en trop pour une fonction, on peut très bien appeler une fonction qui ne prend qu'un seul paramètre (comme alert par exemple).

+ + + +

reduce et reduceRight sont des méthodes itératives plus compliquées. Ces méthodes sont à utiliser pour des algorithmes récursifs pour réduire une séquence d'objet en une seule valeur.

+ +

Tableaux à plusieurs dimensions

+ +

Les tableaux peuvent être imbriqués, cela signifie qu'un tableau peut contenir un autre tableau comme élément. De cette façon, on peut créer des tableaux à plusieurs dimensions.

+ +

Voici par exemple la création d'un tableau de dimension 2.

+ +
var a = new Array(4);
+for (i = 0; i < 4; i++) {
+  a[i] = new Array(4);
+  for (j = 0; j < 4; j++) {
+    a[i][j] = "[" + i + "," + j + "]";
+  }
+}
+
+ +

Le code précédent permettra de créer un tableau avec ces lignes :

+ +
Ligne 0: [0,0] [0,1] [0,2] [0,3]
+Ligne 1: [1,0] [1,1] [1,2] [1,3]
+Ligne 2: [2,0] [2,1] [2,2] [2,3]
+Ligne 3: [3,0] [3,1] [3,2] [3,3]
+
+ +

Tableaux et expressions rationnelles

+ +

Lorsqu'un tableau provient d'une correspondance entre une expression rationnelle et une chaîne de caractères, le tableau possède des propriétés et des éléments fournissant des informations sur la correspondance. Un tel tableau peut être renvoyé par RegExp.exec(), String.match(), et String.split(). Pour plus d'informations sur l'utilisation des tableaux et des expressions rationnelles, voir la page Expressions rationnelles.

+ +

Manipuler des objets semblables aux tableaux

+ +

Certains objets JavaScript, comme NodeList (renvoyé par la méthode document.getElementsByTagName()) ou arguments (disponible au sein d'une fonction) ressemblent à des tableaux et peuvent se comporter comme tels, en revanche ils ne possèdent pas toutes les propriétés d'un objet de type Array. Par exemple, l'objet arguments possède un attribut length mais ne possède pas la méthode forEach().

+ +

Les méthodes génériques, disponibles à partir de JavaScript 1.6, permettent d'utiliser des méthodes de l'objet Array sur des objets semblables à des tableaux. Chaque méthode standard possède un équivalent disponible via l'objet Array lui-même. Ainsi :

+ +
 function alertArguments() {
+   Array.forEach(arguments, function(item) {
+     alert(item);
+   });
+ }
+
+ +

Dans les versions plus anciennes, il est possible d'émuler ces méthodes génériques en utilisant la méthode call fournie par les fonctions :

+ +
 Array.prototype.forEach.call(arguments, function(item) {
+   alert(item);
+ });
+
+ +

Ces méthodes génériques peuvent également être utilisées sur les chaînes de caractères. En effet, elles fournissent un accès séquentiel aux différents caractères, comme pour les différents éléments d'un tableau :

+ +
Array.forEach("une chaine", function(caractere) {
+   alert(caractere);
+});
+ +

Voici d'autres exemples utilisant ces méthodes sur des chaînes de caractères. Ces exemples utilisent également les fermetures d'expressions de JavaScript 1.8 :

+ +
var str = 'abcdef';
+var filtreConsonnes = Array.filter(str, function (c) !(/[aeiou]/i).test(c)).join(''); // 'bcdf'
+var voyellesPrésentes = Array.some(str, function (c) (/[aeiou]/i).test(c)); // true
+var toutesVoyelles = Array.every(str, function (c) (/[aeiou]/i).test(c)); // false
+var intercaleZéros = Array.map(str, function (c) c+'0').join(''); // 'a0b0c0d0e0f0'
+var valeurNumérique = Array.reduce(str, function (c, c2) c+c2.toLowerCase().charCodeAt()-96, 0);
+// 21 (reduce() since JS v1.8)
+
+ +

Les méthodes filter et map ne renvoient pas directement les caractères comme faisant partie d'une même chaîne de caractères mais le résultat de l'opération sur chacun des caractères, il est donc nécessaire d'utiliser join pour obtenir une chaîne de caractères finale.

+ +

Tableaux définis par compréhensions

+ +

À partir de JavaScript 1.7, les définitions de tableaux par compréhension permettent de construire, simplement, un tableau se basant sur le contenu d'un premier tableau. Ces compréhensions sont souvent utilisées en lieu et place des méthodes map() et filter().

+ +

Dans l'exemple suivant, on définit un tableau par compréhension pour qu'il contienne les doubles des éléments du premier tableau :

+ +
var nombres = [1, 2, 3, 4];
+var doubles = [i * 2 for (i of nombres)];
+alert(doubles); // Affiche 2,4,6,8
+
+ +

Cela est équivalent à l'opération map() qui suit :

+ +
var doubles = nombres.map(function(i){return i * 2;});
+
+ +

Les compréhensions peuvent également être utilisées afin de restreindre un tableau à certaines valeurs correspondants à un critère. On peut par exemple ne garder que les nombres pairs :

+ +
var nombres = [1, 2, 3, 21, 22, 30];
+var pairs = [i for (i of nombres) if (i % 2 === 0)];
+alert(pairs); // Affiche 2,22,30
+
+ +

filter() aurait également pu être utilisé :

+ +
var pairs = nombres.filter(function(i){return i % 2 === 0;});
+
+ +

Les opérations du style de map() et filter() peuvent être combinées en une seule compréhension. Voici par exmple un tableau défini par compréhension qui contient les doubles des nombres pairs du premier tableau :

+ +
var nombres = [1, 2, 3, 21, 22, 30];
+var pairsDoubles = [i * 2 for (i of nombres) if (i % 2 === 0)];
+alert(pairsDoubles); // Affiche 4,44,60
+
+ +

Les crochets utilisés pour les définitions par compréhension permettent d'introduire une portée implicite. Les nouvelles variables (comme i dans l'exemple) sont utilisées comme si elles avaient été déclarées avec let. Elles ne seront donc pas disponibles en dehors de la compréhension.

+ +

Il n'est pas nécessaire de partir d'un tableau pour utiliser une telle définition, on peut également utiliser les itérateurs et les générateurs.

+ +

On peut également utiliser des chaînes de caractères comme objet de départ :

+ +
var str = 'abcdef';
+var filtreConsonnes = [c for (c of str) if (!(/[aeiouAEIOU]/).test(c))  ].join(''); // 'bcdf'
+var intercaleZéros = [c+'0' for (c of str) ].join(''); // 'a0b0c0d0e0f0'
+
+ +

Ici aussi, il faut utiliser la méthode join() pour obtenir une chaîne de caractère unique en sortie.

+ +

L'objet Boolean

+ +

L'objet Boolean est une « enveloppe » (ou wrapper en anglais) autour du type primitif booléen. La syntaxe suivante permet de créer un objet Boolean :

+ +
var nomObjetBooléen = new Boolean(valeur);
+
+ +

Attention, il ne faut pas confondre les valeurs true et false du type primitif booléen et les valeurs true et false de l'objet Boolean. Tout objet dont la valeur n'est pas undefined , null, 0, NaN, ou la chaîne de caractères vide (y compris un objet Boolean dont la valeur est false) sera évalué comme true dans un test conditionnel. Voir l'instruction if...else pour plus d'informations.

+ +

Objet Date

+ +

JavaScript ne possède pas de type de données pour gérer les dates. En revanche, il est possible d'utiliser un objet Date, ainsi que ses méthodes, pour manipuler de telles données. L'objet Date possède différentes méthodes pour définir des dates, obtenir des informations sur une dates et les manipuler, il ne possède aucune propriété.

+ +

La gestion des dates en JavaScript est similaire à celle effectuée par Java. Les deux languages partagent de nombreuses méthodes et ils stockent tous les deux les dates comme le nombre de millisecondes depuis le premier janvier 1970 à 00h00m00 UTC.

+ +

L'intervalle qu'on peut utiliser avec l'objet Date est entre100 000 000 jours avant le premier janvier 1970 UTC et 100 000 000 jours après.

+ +

Pour créer un tel objet :

+ +
var nomObjetDate = new Date([paramètres]);
+
+ +

nomObjetDate est le nom de l'objet qu'on crée. Il peut être un nouvel objet à part entière ou bien la propriété d'un objet existant.

+ +

Si on utilise le constructeur Date sans le mot-clé new, on obtiendra seulement la date représentée dans une chaîne de caractères.

+ +

On peut utiliser les paramètres suivants :

+ + + +

Versions antérieures à JavaScript 1.2 (inclus)
+ L'objet Date fonctionne de la façon suivante :

+ + + +

Les méthodes de l'objet Date

+ +

Les méthodes de l'objet Date sont à répartir entre quatre grandes catégories :

+ + + +

Les deux premières catégories permettent de définir ou d'obtenir les secondes, les minutes, les heures, le jour du mois, le jour de la semaine, les mois et les années. Il existe une méthode getDay pour obtenir le jour de la semaine, en revanche, il n'existe pas de méthode setDay car le calcul du jour de la semaine se fait automatiquement. Ces méthodes utilisent des entiers, de la façon suivante :

+ + + +

Par exemple, si on veut définir la date suivante :

+ +
var Noel95 = new Date("December 25, 1995");
+
+ +

On aura alors Noel95.getMonth() qui renverra 11, Noel95.getFullYear() qui renverra 1995.

+ +

Les méthodes getTime et setTime peuvent notamment être utilisées pour comparer des dates. La méthode getTime renvoie le nombre de millisecondes écoulées depuis le premier janvier 1970 00h00m00s pour un objet Date.

+ +

De cette façon, le code suivant permet d'afficher le nombre de jours restants pour l'année courante :

+ +
var ajd = new Date();
+var finAnnee = new Date(1995, 11, 31, 23, 59, 59, 999); // On règle jour et mois
+finAnnee.setFullYear(ajd.getFullYear()); // On règle l'année
+var msParJour = 24 * 60 * 60 * 1000; // Nombre de millisecondes par jour
+var joursRestants = (finAnnee.getTime() - ajd.getTime()) / msParJour;
+var joursRestants = Math.round(joursRestants); //renvoie le nombre de jours restants
+
+ +

Dans cet exemple, on crée un objet Date qui contient la date du jour. Ensuite on crée un objet finAnnee et on fixe son année à celle du jour courant. Ensuite, en connaissant le nombre de millisecondes dans une journée, on calcule le nombre de jours entre ajd et finAnnee en utilisant la méthode getTime puis en arrondissant la valeur à un nombre entier.

+ +

La méthode parse peut s'avérer utile lorsqu'on souhaite transformer une chaîne de caractères (en anglais, attention) en une date. L'exemple qui suit utilise les méthodes parse et setTime pour assigner une valeur de date à l'objet dateIPO :

+ +
var dateIPO = new Date();
+dateIPO.setTime(Date.parse("Aug 9, 1995"));
+
+ +

Exemple d'utilisation

+ +

L'exemple qui suit permet de définir la fonction JSClock() qui renvoie l'heure au même format qu'une horloge numérique :

+ +
function JSClock() {
+  var time = new Date();
+  var heure = time.getHours();
+  var minute = time.getMinutes();
+  var seconde = time.getSeconds();
+  var temp = "" + heure;
+  temp += ((minute < 10) ? ":0" : ":") + minute;
+  temp += ((seconde < 10) ? ":0" : ":") + seconde;
+  return temp;
+}
+
+ +

La fonctionThe JSClock commence par créer un objet Date appelé time. Aucun argument n'est donné, c'est donc la date et l'heure courante. Ensuite, on appelle les méthodes getHours, getMinutes, et getSeconds pour connaître l'heure, les minutes et les secondes.

+ +

Les trois instructions suivantes permettent de construire une chaîne de caractères avec la variable temp. On ajoute l'heure, puis les minutes (si celles-ci sont inférieures à 10, on rajoute un 0 devant), puis les secondes (de la même manière on rajoute un zéro devant si le nombre de secondes est inférieur à 10).

+ +

L'objet Function

+ +

L'objet élémentaire Function définit une chaîne de caractères de code JavaScript qui doit être compilé comme une fonction.

+ +

Pour créer un objet Function on peut utiliser la syntaxe suivante :

+ +
var functionNomObjet = new Function ([arg1, arg2, ... argn], corpsFonction);
+
+ +

functionNomObjet est le nom d'une variable ou d'une propriété d'un objet. On peut également utiliser cette syntaxe avec un objet suivi par un nom de gestionnaire d'événements en minuscules comme window.onerror.

+ +

arg1, arg2, ... argn sont les arguments qui sont utilisés par la fonction. Chacun de ces arguments doit être une chaîne de caractères qui est un identifiant JavaScript valide (ex : "x" ou "monFormulaire".

+ +

corpsFonction est une chaîne de caractères définissant le code JavaScript qui doit être compilé comme le code de la fonction.

+ +

Les objets Function sont évalués à chaque fois qu'ils sont utilisés. Utiliser ces objets est moins efficaces que la déclaration de fonctions qu'on appellera au sein du code. Cela est dû au fait que les fonctions déclarées sont compilées.

+ +

En plus de la définition de fonction abordée ici, on peut également les expressions de fonction ou l'instruction function. Voir la référence JavaScript pour plus d'informations sur ces différentes syntaxes.

+ +

Le code suivant assigne une fonction à la variable setBGColor. Cette fonction permet de définir la couleur d'arrière-plan du document courant.

+ +
var setBGColor = new Function("document.bgColor = 'antiquewhite'");
+
+ +

Pour appeler l'objet Function, on peut utiliser le nom de la variable comme une fonction. Le code qui suit exécute la fonction qui aura été assignée à la variable setBGColor :

+ +
var choixCouleur="antiquewhite";
+if (choixCouleur=="antiquewhite") {setBGColor()}
+
+ +

On peut assigner la fonction à un gestionnaire d'événements de différentes façons :

+ +
    +
  1. +
    document.form1.colorButton.onclick = setBGColor;
    +
    +
  2. +
  3. +
    <INPUT NAME="colorButton" TYPE="button"
    +  VALUE="Changer la couleur de l'arrière-plan"
    +  onClick="setBGColor()">
    +
    +
  4. +
+ +

La création de la variable setBGColor montrée avant est similaire à la fonction suivante :

+ +
function setBGColor() {
+  document.bgColor = 'antiquewhite';
+}
+
+ +

Assigner une fonction à une variable est similaire à la déclaration d'une fonction, cependant il y a quelques différences :

+ + + +

Il est possible d'imbriquer une fonction au sein d'une fonction. La fonction imbriquée est privée, en termes de portée, pour la fonction englobante.

+ + + +

L'objet Math

+ +

L'objet élémentaire Math possède différentes propriétés et méthodes pour manipuler des constantes et des fonctions mathématiques. Ainsi, la propriété PI de cette objet possède la valeur de pi (3.141...) :

+ +
Math.PI
+
+ +

De la même façon, cet objet met a disposition des fonctions mathématiques qui sont des méthodes de l'objet Math. On retrouvera des fonctions trigonométriques, logarithmiques, exponentielles... Ainsi pour utiliser la fonction sinus, on écriera :

+ +
Math.sin(1.56)
+
+ +

Note : les arguments des méthodes trigonométriques de cet objet doivent être exprimés en radians.

+ +

Le tableau suivant liste les différentes méthodes de l'objet Math.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tableau 7.1 Méthodes de l'objet Math
MéthodeDescription
absValeur absolue
sin, cos, tanFonctions trigonométriques sinus, cosinus et tangente
acos, asin, atan, atan2Fonctions trigonométriques inverses, les valeurs renvoyées sont exprimées en radians
exp, logLes fonctions exponentielle et logarithme (naturel ou à base e)
ceilRenvoie le plus petit entier supérieur ou égal à l'argument
floorRenvoie le plus grand entier inférieur ou égal à l'argument
min, maxRenvoie le minimum ou le maximum (respectivement) des deux arguments
powLa fonction puissance, le premier argument est la base et le second argument est l'exposant
randomRenvoie un nombre aléatoire compris entre 0 et 1
roundArrondit l'argument au plus proche entier
sqrtLa fonction racine carrée
+ +

Contrairement à beaucoup d'autres objets, on ne crée jamais d'objet Math personnalisé : on utilise toujours l'objet élémentaire Math.

+ +

L'objet Number

+ +

L'objet Number possède des propriétés correspondantes aux constantes numériques. On y trouve : la valeur maximale qu'il est possible de représenter, la valeur minimale, les infinis (négatifs et positifs), et également la constante « not a number » ou NaN qui indique que la valeur n'est pas un nombre. Ces valeurs sont fixes, ne peuvent être changées et s'utilisent de la façon suivante :

+ +
var maximum = Number.MAX_VALUE;
+var minimum = Number.MIN_VALUE;
+var infiniPlus = Number.POSITIVE_INFINITY;
+var infiniMoins = Number.NEGATIVE_INFINITY;
+var nonNombre = Number.NaN;
+
+ +

Il faut toujours utiliser les propriétés de l'objet Number lui-même et non pas celles d'un objet Number qui aurait été créé.

+ +

Le tableau suivant liste les différents propriétés de l'objet Number :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tableau 7.2 Propriétés de l'objet Number
PropriétéDescription
MAX_VALUELe plus grand nombre qu'on peut représenter
MIN_VALUELe plus petit nombre qu'on peut représenter
NaNValeur spéciale pour les valeurs non numériques
NEGATIVE_INFINITYValeur spéciale pour représenter l'infini négatif
POSITIVE_INFINITYValeur spéciale pour représenter l'infini positif
+ +

Le prototype Number fournit également des méthodes pour obtenir des informations d'objets Number. Le tableau suivant liste ces différentes méthodes de Number.prototype :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tableau 7.3 Méthodes de Number.prototype
MéthodeDescription
toExponentialRenvoie une chaîne de caractères représentant le nombre dans sa notation exponentielle.
toFixedRenvoie une chaîne de caractères représentant le nombre dans sa notation à point fixe.
toPrecisionRenvoie une chaîne de caractères représentant le nombre dans sa notation à point fixe, avec une précision donnée.
toSourceRenvoie un littéral objet représentant l'objet Number. Cette valeur peut ensuite être utilisée pour créer un nouvel objet. Cette méthode surcharge la méthode Object.toSource.
toStringRenvoie une chaîne de caractères représentant l'objet. Cette méthode surcharge la méthode Object.toString.
valueOfRenvoie la valeur primitive de l'objet. Cette méthode surcharge la méthode Object.valueOf.
+ +

L'objet RegExp

+ +

Pour plus d'explications sur le fonctionnement des expressions rationnelles, voir la page sur les expressions rationnelles.

+ +

L'objet String

+ +

L'objet String est une enveloppe pour les données du type chaîne de caractères. Les littéraux de chaînes de caractères ne doivent pas être confondus avec les objets String. Par exemple, le code suivant crée deux choses : un littéral de chaîne de caractère, s1, et l'objet String s2 :

+ +
var s1 = "truc"; //crée un littéral de chaîne de caractères
+var s2 = new String("truc"); //crée un objet String
+
+ +

Chacune des méthodes de l'objet String peut être utilisée sur une valeur qui est un littéral de chaîne de caractères (pour ce faire, JavaScript convertit automatiquement le littéral en un objet String temporaire, appelle la méthode voulue puis supprime l'objet temporaire). Il est également possible d'utiliser la propriété String.length sur un littéral de chaîne de caractères.

+ +

Il est fortement recommandé d'utiliser des littéraux de chaînes de caractères à moins d'avoir spécifiquement besoin d'utiliser un objet String. En effet, les objets String peuvent avoir des effets inattendus :

+ +
var s1 = "2 + 2"; //crée un littéral de chaîne de caractères
+var s2 = new String("2 + 2"); //crée un objet String
+eval(s1); //renvoie 4
+eval(s2); //renvoie la chaîne "2 + 2"
+ +

Un objet String possède une seule propriété, length, indiquant le nombre de caractères contenus dans la chaîne de caractères. Dans le code qui suit, x recevra la valeur 13 car la chaîne "Hello, World!" possède 13 caractères :

+ +
var maChaine = "Hello, World!";
+var x = maChaine.length;
+
+ +

Un objet possède deux types de méthodes : celles qui renvoient une chaîne modifiée à partir de l'objet initial et celles qui renvoient une version au format HTML de la chaîne. Dans la première catégorie on trouvera des méthodes comme substring et toUpperCase, dans la seconde catégorie, on trouvera notamment bold et link.

+ +

Par exemple, si on utilise la chaîne précédente maChaine.toUpperCase() ou aussi "hello, world!".toUpperCase(), on obtiendra le résultat "HELLO, WORLD!".

+ +

La méthode substring contient deux arguments et renvoie un fragment de la chaîne de caractères entre ces deux arguments qui correspondent aux indices de début et de fin du « découpage ». maChaine.substring(4, 9) renverra "o, Wo".

+ +

L'objet String possède également certaines méthodes permettant d'obtenir directement des données au format HTML : des liens, du texte formaté... Ainsi on pourrait créer un hyperlien avec la méthode suivante :

+ +
maChaine.link("http://www.helloworld.com")
+
+ +

Le tableau qui suit liste les méthodes des objets String.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tableau 7.4 Méthodes des instances du prototype String
MéthodeDescription
anchorPermet de créer un ancre HTML
big, blink, bold, fixed, italics, small, strike, sub, supPermet de formater une chaîne de caractères au format HTML. (Note : l'utilisation du CSS peut parfois être plus judicieuse que certaines entités HTML).
charAt, charCodeAtRenvoie le caractère ou le code du caractère à la position indiquée dans la chaîne de caractères.
indexOf, lastIndexOfRenvoie la position d'un fragment de la chaîne de caractères (respectivement la dernière position).
linkCrée un hyperlien HTML
concatConcatène deux chaînes de caractères en une chaîne de caractères.
fromCharCodeConstruit une chaîne de caractères à partir de la séquence de codes Unicodes fournie. Cette méthode appartient au prototype String mais pas aux instances objets String.
splitDécoupe un objet String en un tableau de chaînes de caractères selon un séparateur donné.
sliceExtrait un fragment de la chaîne de caractères et renvoie une nouvelle chaîne.
substring, substrRenvoie un fragment de la chaîne de caractères à partir d'un indice jusqu'à un autre indice ou à partir d'un indice et pour une longueur donnée.
match, replace, searchFonctionne avec les expressions rationnelles.
toLowerCase, toUpperCase +

Renvoie la chaîne de caractères en lettres minuscules (respectivement, en lettres majuscules).

+
+ +

« Précédent  Suivant »

diff --git "a/files/fr/web/javascript/guide/retours_sur_h\303\251ritage/index.html" "b/files/fr/web/javascript/guide/retours_sur_h\303\251ritage/index.html" new file mode 100644 index 0000000000..fc7d26e6db --- /dev/null +++ "b/files/fr/web/javascript/guide/retours_sur_h\303\251ritage/index.html" @@ -0,0 +1,87 @@ +--- +title: Retours sur l'héritage +slug: Web/JavaScript/Guide/Retours_sur_héritage +tags: + - Guide + - JavaScript + - Prototype +translation_of: Web/JavaScript/Inheritance_and_the_prototype_chain +--- +

Pour des informations plus générales sur l'héritage et les prototypes dans JavaScript, il est conseillé de lire la page Héritage et chaîne de prototypes.

+ +

L'héritage a toujours été présent dans JavaScript. Les exemples de cette page utilisent des méthodes qui ont été introduites avec ECMAScript 5. Les pages décrivant ces méthodes vous permettront de savoir si elles peuvent être émulées ou non (pour les anciennes versions notamment).

+ +

Exemple

+ +

B hérite de A :

+ +
function A(a){
+  this.varA = a;
+}
+
+A.prototype = {
+  faireQuelqueChose : function(){
+    // ...
+  }
+}
+
+function B(a, b){
+  A.call(this, a);
+  this.varB = b;
+}
+B.prototype = Object.create(A.prototype, {
+  varB : {
+    value: null,
+    enumerable: true,
+    configurable: true,
+    writable: true
+  },
+  faireQuelqueChose : {
+    value: function(){ // surcharge
+      A.prototype.faireQuelqueChose.apply(this, arguments); // call super
+      // ...
+    },
+    enumerable: true,
+    configurable: true,
+    writable: true
+  }
+});
+
+var b = new B();
+b.faireQuelqueChose();
+
+ +

Ce qui est à retenir ici :

+ + + +

La propriété prototype et la méthode Object.getPrototypeOf

+ +

JavaScript peut paraître déroutant, relativement à Java ou C++ car il y a une gestion dynamique, à l'exécution et qu'il n'y a pas de classe. Tous les objets sont des instances.

+ +

On voit dans l'exemple précédent que la fonction A possède une propriété spéciale appelée prototype. Cette propriété spéciale est liée à l'utilisation de l'opérateur new. Une référence à l'objet prototype est copié vers la propriété interne [[Prototype]] de la nouvelle instance. Ainsi, si on fait var a1 = new A(), JavaScript (une fois que l'objet sera créé en mémoire et avant d'exécuter la fonction A() avec this lié à l'objet) définira a1.[[Prototype]] = A.prototype. Quand on accède aux propriétés d'une instance, JavaScript vérifie d'abord que la propriété en question existe ou non pour l'instance même et si ce n'est pas le cas, consulte [[Prototype]]. Cela signifie que chaque chose définie dans prototype est partagée avec toutes les instances et qu'on peut changer certains aspects du prototype par la suite, ces changements seront répercutés pour toutes les instances.

+ +

Si, dans l'exemple suivant, on fait var a1 = new A(); var a2 = new A(); alors a1.faireQuelqueChose se référerait à Object.getPrototypeOf(a1).faireQuelqueChose, qui correspond exactement à A.prototype.faireQuelqueChose. Autrement dit : Object.getPrototypeOf(a1).faireQuelqueChose == Object.getPrototypeOf(a2).faireQuelqueChose == A.prototype.faireQuelqueChose.

+ +

En résumé, le prototype correspond au type tandis que Object.getPrototypeOf() permet de décrire une instance.

+ +

[[Prototype]] est exploré récursivement. Cela signifie qu'on cherche a1.faireQuelqueChose, puis Object.getPrototypeOf(a1).faireQuelqueChose, puis Object.getPrototypeOf(Object.getPrototypeOf(a1)).faireQuelqueChose et ainsi de suite jusqu'à ce que Object.getPrototypeOf renvoie la valeur null.

+ +

Quand on appelle :

+ +
var o = new Toto();
+ +

JavaScript effectue en fait :

+ +
var o = new Object();
+o.[[Prototype]] = Toto.prototype;
+o.Toto();
+ +

Puis, si on utilise cette instruction

+ +
o.unePropriété;
+ +

qui vérifie si o possède une propriété unePropriété. Si ce n'est pas le cas, JavaScript vérifiera si Object.getPrototypeOf(o).unePropriété existe, si ce n'est pas le cas il vérifie Object.getPrototypeOf(Object.getPrototypeOf(o)).unePropriété et ainsi de suite.

diff --git a/files/fr/web/javascript/guide/types_et_grammaire/index.html b/files/fr/web/javascript/guide/types_et_grammaire/index.html new file mode 100644 index 0000000000..e2c51c9cc3 --- /dev/null +++ b/files/fr/web/javascript/guide/types_et_grammaire/index.html @@ -0,0 +1,709 @@ +--- +title: Types et grammaire +slug: Web/JavaScript/Guide/Types_et_grammaire +tags: + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +
 {{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Contrôle_du_flux_Gestion_des_erreurs")}}
+ +

Ce chapitre décrit les bases de la grammaire et des types de données JavaScript.

+ +

Les bases du langage

+ +

JavaScript emprunte la plupart des éléments de sa syntaxe à Java, C et C++ mais sa syntaxe est également influencée par Awk, Perl et Python.

+ +

JavaScript est sensible à la casse et utilise l'ensemble de caractères Unicode. On pourrait donc tout à fait utiliser le mot früh comme nom de variable :

+ +
var früh = "toto";
+typeof Früh; // undefined car JavaScript est sensible à la casse
+
+ +

En JavaScript, les instructions sont appelées ({{Glossary("Statement", "statements")}}) et sont séparées par des points-virgules.

+ +

Il n'est pas nécessaire d'inclure un point-virgule si l'on écrit une instruction sur une nouvelle ligne. Mais si vous voulez écrire plus d'une déclaration sur une seule ligne, alors elles doivent être séparées par un point-virgule. Ceci étant dit, la bonne pratique est d'inclure un point-virgule après chaque instruction. Les espaces, les tabulations et les caractères de nouvelles lignes sont considérés comme des blancs. Il existe aussi un ensemble de règles pour ajouter automatiquement des points-virgules à la fin des instructions (ASI pour Automatic Semicolon Insertion). Cependant, il est conseillé de toujours ajouter des points-virgules à la fin des instructions afin d'éviter des effets de bord néfastes.

+ +

Le texte d'un code source JavaScript est analysé de gauche à droite et est converti en une série d'unités lexicales, de caractères de contrôle, de fins de lignes, de commentaires et de blancs. ECMAScript définit également certains mots-clés et littéraux. Pour plus d'informations, voir la page sur la grammaire lexicale de JavaScript dans la référence JavaScript.

+ +

Commentaires

+ +

La syntaxe utilisée pour les commentaires est la même que celle utilisée par le C++ et d'autres langages :

+ +
// un commentaire sur une ligne
+
+/* un commentaire plus
+   long sur plusieurs lignes
+ */
+
+/* Par contre on ne peut pas /* imbriquer des commentaires */ SyntaxError */
+
+ +
+

Note : Vous pourrez également rencontrer une troisième forme de commentaires au début de certains fichiers JavaScript comme #!/usr/bin/env node. Ce type de commentaire indique le chemin d'un interpréteur JavaScript spécifique pour exécuter le script. Pour plus de détails, voir la page sur les commentaires d'environnement.

+
+ +

Déclarations

+ +

Il existe trois types de déclarations de variable en JavaScript.

+ +
+
{{jsxref("Instructions/var", "var")}}
+
On déclare une variable, éventuellement en initialisant sa valeur.
+
{{jsxref("Instructions/let", "let")}}
+
On déclare une variable dont la portée est celle du bloc courant, éventuellement en initialisant sa valeur.
+
{{jsxref("Instructions/const", "const")}}
+
On déclare une constante nommée, dont la portée est celle du bloc courant, accessible en lecture seule.
+
+ +

Variables

+ +

Les variables sont utilisées comme des noms symboliques désignant les valeurs utilisées dans l'application. Les noms des variables sont appelés identifiants. Ces identifiants doivent respecter certaines règles.

+ +

Un identifiant JavaScript doit commencer par une lettre, un tiret bas (_) ou un symbole dollar ($). Les caractères qui suivent peuvent être des chiffres (0 à 9).
+ À noter: puisque Javascript est sensible aux majuscules et minuscules: les lettres peuvent comprendre les caractères de « A » à « Z » (en majuscule) mais aussi les caractères  de « a » à « z » (en minuscule).

+ +

On peut aussi utiliser la plupart lettres Unicode ou ISO 8859-1 (comme å et ü, pour plus de détails, voir ce billet de blog, en anglais) au sein des identifiants. Il est également possible d'utiliser les \uXXXX séquences d'échappement Unicode comme caractères dans les identifiants.

+ +

Voici des exemples d'identifiants valides : Nombre_touches, temp99, $credit, et _nom.

+ +

Déclaration de variables

+ +

Il est possible de déclarer des variables de plusieurs façons :

+ + + +

Il est également possible d'affecter une valeur à une variable sans utiliser de mot-clé (ex. x = 42). Cela créera une variable globale non-déclarée. Cette forme génèrera également un avertissement avec le mode strict. Attention, les variables globales non-déclarées peuvent mener à des comportements inattendus et sont considérées comme une mauvaise pratique.

+ +

Évaluation de variables

+ +

Une variable déclarée grâce à l'instruction var ou let sans valeur initiale définie vaudra {{jsxref("undefined")}}.

+ +

Tenter d'accéder à une variable qui n'a pas été déclarée ou tenter d'accéder à un identifiant déclaré avec let avant son initialisation provoquera l'envoi d'une exception {{jsxref("ReferenceError")}}.

+ +
var a;
+console.log("La valeur de a est " + a); // La valeur de a est undefined
+
+console.log("La valeur de b est " + b); // La valeur de b est undefined
+var b; // La déclaration de la variable est "remontée" (voir la section ci-après)
+
+console.log("La valeur de x est " + x); // signale une exception ReferenceError
+let x;
+let y;
+console.log("La valeur de y est " + y); // La valeur de y est undefined
+
+ +

Il est possible d'utiliser undefined pour déterminer si une variable possède une valeur. Dans l'exemple qui suit, la condition de l'instruction if sera validée car la variable n'a pas été initialisée (elle a simplement été déclarée) :

+ +
var input;
+if (input === undefined){
+  faireCeci();
+} else {
+  faireCela();
+}
+
+ +

La valeur undefined se comporte comme le booléen false lorsqu'elle est utilisée dans un contexte booléen. Ainsi, le fragment de code qui suit exécutera la fonction maFonction puisque le premier élément de monTableau n'est pas défini :

+ +
var monTableau = new Array();
+if (!monTableau[0]){
+  maFunction();
+}
+
+ +

La valeur undefined est convertie en {{jsxref("NaN")}} (pour Not a Number : « n'est pas un nombre ») lorsqu'elle est utilisée dans un contexte numérique.

+ +
var a;
+a + 2; // NaN
+ +

Une variable valant null sera toujours considérée comme 0 dans un contexte numérique et comme false dans un contexte booléen. Par exemple, on aura :

+ +
var n = null;
+console.log(n * 32); // Le log affichera 0
+ +

Les portées de variables

+ +

Lorsqu'une variable est déclarée avec var en dehors des fonctions, elle est appelée variable globale car elle est disponible pour tout le code contenu dans le document. Lorsqu'une variable est déclarée dans une fonction, elle est appelée variable locale car elle n'est disponible qu'au sein de cette fonction.

+ +

Avant ECMAScript 2015 (ES6), JavaScript ne définissait pas de portée pour une instruction de bloc ; les éléments du bloc seront locaux pour le code qui contient le bloc (que ce soit une fonction ou le contexte global). Ainsi, l'exemple qui suit affichera 5 car la portée de x est la fonction (ou le contexte global) dans lequel x est déclaré, pas le bloc (correspondant à l'instruction if dans ce cas) :

+ +
if (true) {
+  var x = 5;
+}
+console.log(x); // x vaut 5
+
+ +

La déclaration {{jsxref("Instructions/let","let")}}, introduite avec ECMAScript 2015, ajoute un nouveau comportement :

+ +
if (true) {
+  let y = 5;
+}
+console.log(y); // ReferenceError: y is not defined
+
+ +

Remontée de variables (hoisting)

+ +

Une autre chose peut paraître étrange en JavaScript : il est possible, sans recevoir d'exception, de faire référence à une variable qui est déclarée plus tard. Ce concept est appelé « remontée » (hoisting en anglais) car, d'une certaine façon, les variables sont remontées en haut de la fonction ou de l'instruction. En revanche, les variables qui n'ont pas encore été initialisées renverront la valeur undefined. Ainsi, même si on déclare une variable et qu'on l'initialise après l'avoir utilisée ou y avoir fait référence, la valeur utilisée « la plus haute » sera toujours undefined.

+ +
/**
+ * Exemple 1
+ */
+console.log(x === undefined); // donne "true"
+var x = 3;
+
+/**
+ * Exemple 2
+ */
+// renverra undefined
+var maVar = "ma valeur";
+
+(function () {
+  console.log(maVar); // undefined
+  var maVar = "valeur locale";
+})();
+
+ +

Les exemples précédents peuvent être reformulés plus explicitement ainsi :

+ +
/**
+ * Exemple 1
+ */
+var x;
+console.log(x === undefined); // donne "true"
+x = 3;
+
+/**
+ * Exemple 2
+ */
+var maVar = "ma valeur";
+
+(function () {
+  var maVar;
+  console.log(maVar); // undefined
+  maVar = "valeur locale";
+})();
+
+ +

C'est pourquoi il est conseillé de placer les instructions var dès que possible dans le code. De plus, cette bonne pratique aide à rendre le code plus lisible.

+ +

Avec ECMAScript 2015, let (const) remontera la variable en haut du bloc mais ne l'initialisera pas. Aussi, si on fait référence à la variable dans le bloc avant la déclaration, on obtient une {{jsxref("ReferenceError")}} car la variable est dans une « zone morte temporelle ». entre le début du bloc et le traitement de la déclaration

+ +
function faire_quelquechose() {
+  console.log(toto); // ReferenceError
+  let toto = 2;
+}
+ +

Remontée de fonctions

+ +

En ce qui concerne les fonctions, seules les déclarations de fonctions sont remontées. Pour les expressions de fonctions, il n'y a pas de telle remontée car la variable associée n'a pas encore été affectée avec la valeur finale (comme vu avant) :

+ +
/* Déclaration de fonction */
+toto();  // "truc"
+function toto(){
+  console.log("truc");
+}
+
+/* Expression de fonction */
+machin();      // erreur TypeError : machin n'est pas une fonction
+var machin = function() {
+  console.log("titi");
+}
+
+ +

Les variables globales

+ +

Les variables globales sont en réalité des propriétés de l'objet global. Dans les pages web, l'objet global est {{domxref("window")}}, et on peut donc accéder ou modifier la valeur de variables globales en utilisant la syntaxe suivante : window.variable .

+ +

Ainsi, il est possible d'accéder à des variables déclarées dans une fenêtre ou dans un cadre depuis une autre fenêtre ou depuis un autre cadre (frame) en spécifiant son nom. Si, par exemple, une variable appelée numTéléphone est déclarée dans un document FRAMESET, il est possible d'y faire référence, depuis un cadre fils, avec la syntaxe parent.numTéléphone.

+ +

Constantes

+ +

Il est possible de créer des constantes en lecture seule en utilisant le mot-clé {{jsxref("Instructions/const","const")}}. La syntaxe d'un identifiant pour une constante est la même que pour les variables (elle doit débuter avec une lettre, un tiret du bas, un symbole dollar et peut contenir des caractères numériques, alphabétiques et des tirets bas voire des caractères Unicode).

+ +
const préfixe = '212';
+
+ +

Une constante ne peut pas changer de valeur grâce à une affectation ou être re-déclarée pendant l'exécution du script.

+ +

Les règles de portée des constantes sont les mêmes que pour les variables, à l'exception du mot-clé const qui est obligatoire. S'il est oublié, l'identifiant sera considéré comme celui d'une variable.

+ +

Il est impossible de déclarer une constante avec le même nom qu'une autre variable ou fonction dans la même portée.

+ +
// Renverra une erreur
+function f() {};
+const f = 5;
+
+// Renverra également une erreur
+function f() {
+  const g = 5;
+  var g;
+
+  //instructions
+}
+
+ +

Cependant, les propriétés des objets qui sont affectés comme constantes ne sont pas protégées, on pourra ainsi exécuter sans problème le code suivant :

+ +
const MON_OBJET = {"clé": "valeur"};
+MON_OBJET.clé = "autreValeur";
+ +

De même, le contenu d'un tableau peut être modifié sans alerte :

+ +
const MON_TABLEAU = ["HTML", "CSS"];
+MON_TABLEAU.push("JavaScript");
+console.log(MON_TABLEAU); // ["HTML", "CSS", "JavaScript"]
+
+ +

Structures de données et types

+ +

Types de données

+ +

La dernière version du standard ECMAScript définit sept types de données :

+ + + +

Bien que cette description couvre peu de types de données, ceux-ci vous permettent d'implémenter une grande variété de fonctions au sein de vos applications. Les objets et les fonctions sont parmi les briques fondamentales du langage. On peut considérer, à première vue, les objets comme des conteneurs de valeurs et de fonctions pour une application.

+ +

Conversion de types de données

+ +

JavaScript est un langage à typage dynamique. Cela signifie qu'il n'est pas nécessaire de spécifier le type de données d'une variable lors de sa déclaration. Les types de données sont convertis automatiquement durant l'exécution du script. Ainsi, il est possible de définir une variable de cette façon :

+ +
+
var réponse = 42;
+
+
+ +

Et plus tard, d'affecter une chaîne de caractères à cette même variable :

+ +
+
réponse = "Merci pour le dîner...";
+
+
+ +

JavaScript utilisant un typage dynamique, cette dernière instruction ne renverra pas d'erreur.

+ +

Lorsque des expressions impliquent des chaînes de caractères et des valeurs numériques ainsi que l'opérateur +, JavaScript convertit les nombres en chaînes de caractères :

+ +
x = "La réponse est " + 42; // "La réponse est 42"
+y = 42 + " est la réponse"; // "42 est la réponse"
+
+ +

Avec des instructions impliquant d'autres opérateurs, JavaScript ne convertit pas nécessairement les valeurs numériques en chaînes de caractères. Ainsi, on aura :

+ +
"37" - 7; // 30
+"37" + 7; // "377"
+
+ +

Conversion de chaînes de caractères en nombres

+ +

Si un nombre est représenté en mémoire par une chaîne de caractères, il y a des méthodes pour effectuer la bonne conversion :

+ + + +

parseInt renverra uniquement des nombres entiers, étant ainsi inappropriée pour la manipulation de nombre décimaux. Une bonne pratique pour cette fonction est de toujours inclure l'argument qui indique dans quelle base numérique le résultat doit être renvoyé (base 2, base 10...).

+ +
parseInt("101", 2); // 5
+ +

L'opérateur + unaire

+ +

Une autre méthode pour récupérer un nombre à partir d'une chaîne de caractères consiste à utiliser l'opérateur +.

+ +
"1.1" + "1.1" = "1.11.1"
++"1.1" = 1.1 // fonctionne seulement avec le + unaire
+
+ +

Littéraux

+ +

Les littéraux sont utilisés pour représenter des valeurs en JavaScript. Ce sont des valeurs fixes, pas des variables, qui sont fournies littéralement au script. Cette section décrit les différents types de littéraux :

+ + + +

Les littéraux de tableaux

+ +

Un littéral de tableau est une liste de zéro ou plusieurs expressions, dont chacune représente l'élément d'un tableau, encadrées par des crochets ([]). Lorsqu'un tableau est créé à partir d'un littéral, il est initialisé avec les valeurs spécifiées qui sont ses éléments, sa longueur correspondant au nombre d'arguments donnés.

+ +

L'exemple suivant crée ainsi le tableau cafés avec trois éléments et une taille égale à 3 :

+ +
var cafés = ["Brésilien", "Colombien", "Kona"];
+
+ +
+

Note : Un littéral de tableau est du type d'un initialisateur d'objets. Voir l'utilisation d'initialisateurs d'objets.

+
+ +

Si un tableau est créé en utilisant un littéral dans un script du plus haut niveau, JavaScript interprète le tableau chaque fois qu'il évalue l'expression contenant le littéral. De plus, un littéral utilisé dans une fonction est créé chaque fois que la fonction est appelée.

+ +

Les littéraux de tableaux sont également des objets Array. Voir la page sur l'objet Array pour plus de détails.

+ +

Les virgules supplémentaires

+ +

Il n'est pas nécessaire de définir tous les éléments dans un littéral de tableau. Si vous utilisez deux virgules, l'une à la suite de l'autre, le tableau utilisera la valeur undefined pour les éléments non définis. L'exemple qui suit utilise le tableau poisson :

+ +
var poisson = ["Clown", , "Chat"];
+
+ +

Ce tableau possède deux éléments ayant une valeur et un élément vide (poisson[0] vaut "Clown", poisson[1] vaut undefined, et poisson[2] vaut "Chat").

+ +

Si une virgule est ajoutée à la fin de la liste des éléments, elle est ignorée. Dans le prochain exemple, la longueur du tableau est égale à 3. Il n'y a pas d'élément maListe[3]. Les autres virgules indiquent un nouvel élément.

+ +
+

Note : Avec d'anciennes versions de navigateurs, les virgules de fin peuvent causer des erreurs, il est fortement conseillé de les retirer.

+
+ +
var maListe = ['maison', , 'école', ];
+
+ +

Dans l'exemple qui suit, la longueur du tableau est égale à 4 et maListe[0] et maListe[2] sont manquants.

+ +
var maListe = [ , 'maison', , 'école'];
+
+ +

Dans l'exemple qui suit, la longueur du tableau est égale à 4 et maListe[1] et maListe[3] sont manquants.

+ +
var maListe = ['maison', , 'école', , ];
+
+ +

Comprendre le fonctionnement des virgules supplémentaires est important. Cependant, lorsque vous écrivez du code, veillez, dès que c'est possible, à déclarer les éléments manquants avec undefined : cela améliorera la lisibilité de votre code et il sera ainsi plus facile à maintenir.

+ +

Les littéraux booléens

+ +

Le type booléen possède deux valeurs littérales : true et false.

+ +

Il ne faut pas confondre les valeurs true et false du type primitif booléen et les valeurs true et false de l'objet Boolean. L'objet Boolean permet de créer un objet autour du type de donnée booléen. Voir la page sur l'objet Boolean pour plus d'informations.

+ +

Les littéraux numériques

+ +

Les nombres {{jsxref("Number")}} et les grands entiers {{jsxref("BigInt")}} peuvent être exprimés en notation décimale (base 10), hexadécimale (base 16), octale (base 8) et binaire (base 2).

+ + + +

Voici des exemples pour ces littéraux :

+ +
0, 117, -345, 123456789123456789n (notation décimale, base 10)
+015, 0001, -077, 0o7777777777777n (notation octale, base 8)
+0x1123, 0x00111, -0xF1A7, 0x123456789ABCDEFn (notation hexadécimale, base 16)
+0b11, 0B0011, -0b11, 0b11101001010101010101n (notation binaire, base 2)
+
+ +

Pour plus d'informations, voir les littéraux numériques dans la grammaire lexicale de JavaScript.

+ +

Les littéraux de nombres décimaux

+ +

Un littéral de nombre décimal peut être composé de ces différentes parties :

+ + + +

L'exposant est la partie du nombre décimal commençant par un « e » ou un « E », suivie d'un entier pouvant être signé (précédé d'un « + » ou d'un « - »). Un littéral de nombre décimal doit comporter au moins un chiffre et soit un point (séparateur décimal) soit un « e » ou un « E ».

+ +

Des exemples sont : 3.1415, -3.1E12, .1e12, et 2E-12.

+ +

On peut raccourcir cette syntaxe en :

+ +
[(+|-)][chiffres].[chiffres][(E|e)[(+|-)]chiffres]
+
+ +

Par exemple :

+ +
3.14
+2345.789
+.3333333333333333333
+
+ +

Les littéraux d'objets

+ +

Un littéral d'objet - ou 'objet littéral' - est une liste de zéro ou plusieurs propriétés définies par des paires de noms/valeurs. Ces paires sont délimitées par des accolades ({}). N'utilisez pas un tel littéral en début d'instruction. En effet, l'accolade ouvrante sera mal interprétée (début de bloc) et causera une erreur ou un comportement incohérent.

+ +

L'exemple qui suit montre l'utilisation d'un littéral d'objet. Le premier élément de l'objet voiture définit une propriété maVoiture, le deuxième élément : la propriété getVoiture invoque une fonction (carTypes("Honda")), le troisième élément, la propriété special utilise une variable existante (soldes).

+ +
var soldes = "Toyota";
+
+function carTypes(nom) {
+  return (nom === "Honda") ?
+    nom :
+    "Désolé, nous ne vendons pas de " + nom + "." ;
+}
+
+var voiture = { maVoiture: "Saturn", getVoiture: carTypes("Honda"), spécial: soldes };
+
+console.log(voiture.maVoiture);   // Saturn
+console.log(voiture.getVoiture);  // Honda
+console.log(voiture.spécial); // Toyota
+
+ +

Il est également possible d'utiliser un littéral numérique ou un littéral de chaîne de caractères pour désigner le nom d'une propriété ou pour imbriquer un objet dans un autre. L'exemple qui suit illustre cette possibilité :

+ +
var voiture = { plusieursVoitures: {a: "Saab", b: "Jeep"}, 7: "Mazda" };
+
+console.log(voiture.plusieursVoitures.b); // Jeep
+console.log(voiture[7]); // Mazda
+
+ +

Les noms des propriétés d'objets peuvent être n'importe quelle chaîne de caractères, y compris la chaîne vide. Si le nom de la propriété n'est pas un identifiant valide, il faudra qu'il soit placé entre guillemets. Les noms de propriétés qui ne sont pas des identifiants valides ne peuvent pas être utilisés pour accéder à la valeur en utilisant la notation pointée (objet.propriété). En revanche, il est possible d'y accéder avec la notation utilisant les crochets ("[]") comme pour les tableaux.

+ +
var nomsBizarres = {
+  "": "Chaîne vide",
+  "!": "Bang !"
+}
+console.log(nomsBizarres."");   // SyntaxError: Unexpected string
+console.log(nomsBizarres[""]);  // Chaîne vide
+console.log(nomsBizarres.!);    // SyntaxError: Unexpected token !
+console.log(nomsBizarres["!"]); // Bang !
+
+
+ +

Augmentation des littéraux d'objets avec ES2015/ES6

+ +

Avec ES2015, les littéraux d'objets permettent de définir le prototype lors de la construction de l'objet, permettent d'utiliser les affectations en notation raccourcie : toto: toto, de définir des méthodes, d'appeler les méthodes de l'objet parent avec super et d'utiliser des noms de propriétés calculées.

+ +
var obj = {
+    // __proto__
+    __proto__: lePrototypeDeLObjet,
+    // Notation raccourcie pour ‘handler: handler’
+    handler,
+    // Méthodes
+    toString() {
+     // Appelle les méthodes de l'objet parent
+     return "d " + super.toString();
+    },
+    // Noms de propriétés calculés dynamiquement
+    [ 'prop_' + (() => 42)() ]: 42
+};
+ +

Attention :

+ +
var toto = {a: "alpha", 2: "deux"};
+console.log(toto.a);    // alpha
+console.log(toto[2]);   // deux
+//console.log(toto.2);  // Erreur: parenthèse ) manquante après la liste d'argument
+//console.log(toto[a]); // Erreur: a n'est pas défini
+console.log(toto["a"]); // alpha
+console.log(toto["2"]); // deux
+
+ +

Les littéraux d'expressions rationnelles

+ +

Un littéral d'expression rationnelle est un motif encadré par deux barres obliques. Par exemple :

+ +
var re = /ab+c/;
+ +

Les littéraux de chaînes de caractères

+ +

Un littéral de chaîne de caractères consiste en zéro ou plusieurs caractères encadrés par des guillemets droits doubles (") ou des guillemets droits simples ('). Une chaîne de caractères doit être encadrée par des symboles du même type (guillemets droits doubles ou guillemets droits simples) :

+ + + +

Il est possible d'utiliser les méthodes de String sur un tel littéral. JavaScript convertira automatiquement le littéral en un objet String, appellera la méthode puis détruira l'objet String. On peut également utiliser la propriété String.length sur un littéral de chaîne de caractère :

+ +
console.log("j'ai mangé une pomme".length)
+// Affichera le nombre de caractères (y compris les blancs).
+// Dans ce cas, 20.
+
+ +

Il est préférable d'utiliser des littéraux de chaînes de caractères s'il n'est pas spécifiquement nécessaire d'utiliser un objet String. Voir la page sur l'objet String pour plus de détails sur les objets String.

+ +

Avec ECMAScript 2015, on peut également utiliser des littéraux sous forme de gabarits (templates) en utilisant le caractère accent grave (`) comme séparateur. Les gabarits de chaînes de caractères sont semblables aux fonctionnalités d'interpolation existantes en Python, Perl, etc. Ces gabarits permettent d'utiliser des balises afin d'adapter la construction de chaînes.

+ +
// Littéral simple pour une chaîne
+`Un saut de ligne '\n' en JavaScript.`
+
+// On peut écrire une chaîne sur plusieurs
+// lignes
+`Dans les gabarits, on peut écrire
+  sur plusieurs lignes. `
+
+// Interpolation de chaîne
+var nom = "Robert", jour = "aujourd'hui";
+`Bonjour ${nom}, comment allez-vous ${jour} ?`
+
+// On peut construire un préfixe HTTP
+// afin de construire plus facilement
+// des requêtes via des substitutions
+POST`http://toto.org/truc?a=${a}&b=${b}
+     Content-Type: application/json
+     X-Credentials: ${credentials}
+     { "toto": ${toto},
+       "truc": ${truc}}`(myOnReadyStateChangeHandler);
+ +

Utilisation des caractères spéciaux

+ +

En plus des caractères « classiques », il est possible d'insérer des caractères spéciaux dans les chaînes de caractères. Voici un exemple :

+ +
"une ligne \n une autre ligne"
+
+ +

Voici un tableau listant les caractères spéciaux qu'il est possible d'utiliser dans les chaînes de caractères JavaScript :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Caractères spéciaux en JavaScript
CaractèreSignification
\0Octet null
\bRetour arrière
\fSaut de page
\nNouvelle ligne
\rRetour chariot
\tTabulation
\vTabulation verticale
\'Apostrophe ou guillemet droit simple
\"Guillemet droit double
\\Barre oblique inversée
\XXXLe caractère dont l'encodage Latin-1 est spécifié grâce à, au plus, 3 chiffres octaux XXX entre 0 et 377. \251, par exemple représente le caractère copyright.
\xXXLe caractère dont l'encodage Latin-1 est spécifié par deux chiffres hexadécimaux entre 00 et FF. Ainsi, \xA9 correspond à la séquence hexadécimale pour le caractère copyright.
\uXXXXLe caractère Unicode spécifié par quatre chiffres hexadécimaux XXXX. Ainsi, \u00A9 correspondra à la séquence Unicode du symbole copyright. Voir {{anch("Unicode escape sequences")}}.
\u{XXXXX}Échappement de codes Unicode. Par exemple, \u{2F804} est équivalent à la combinaison d'échappements « simples » \uD87E\uDC04.
+ +

Les caractères d'échappement

+ +

Pour les caractères qui ne font pas partie du tableau précédent, les barres obliques inversées (backslash) les précédant sont ignorées. Cependant, cet usage est obsolète et devrait être évité.

+ +

En précédant d'une barre oblique inversée les guillemets droits doubles, on échappe ces caractères. Voici un exemple :

+ +
var citation = "Il lit \"Bug Jargal\" de V. Hugo.";
+console.log(citation);
+
+ +

Le résultat serait alors

+ +
Il lit "Bug Jargal" de V. Hugo.
+ +

Pour inclure une barre oblique inversée dans une chaîne de caractères, il faut aussi l'échapper. Par exemple, pour stocker le chemin c:\temp dans une chaîne de caractères, on utilisera le code suivant :

+ +
var chemin = "c:\\temp";
+
+ +

Il est également possible d'échapper des sauts de lignes de la même façon. La barre oblique inversée et le saut de ligne seront alors ignorés dans la valeur de la chaîne de caractères.

+ +
var str = "cette chaîne \
+est cassée \
+sur plusieurs \
+lignes."
+console.log(str);   // cette chaîne est cassée sur plusieurs lignes.
+
+ +

Avant ECMAScript 2015 (ES6), JavaScript ne disposait pas d'une syntaxe permettant de traiter les chaînes de caractères comme des contenus de fichier, il est possible d'ajouter un caractère de saut de ligne échappé et un saut de ligne en fin de ligne en utilisant cette façon :

+ +
var poème =
+"Les roses sont rouges,\n\
+Les violettes sont bleues.\n\
+Le miel est sucré,\n\
+Et moi je suis."
+
+ +

Grâce à ES6, on peut utiliser des littéraux de gabarits qui offrent de nouvelles fonctionnalités dont une qui permet d'avoir des chaînes de caractères écrites sur plusieurs lignes :

+ +
var poème =
+`Les roses sont rouges,
+Les violettes sont bleues,
+Le miel est sucré,
+Et moi je suis.`
+ +

En savoir plus

+ +

Ce chapitre est centré sur les bases de la syntaxe, les déclarations et les types utilisés en JavaScript. Pour en savoir plus sur les différents composants du langage, voir les chapitres suivants du guide:

+ + + +

Dans le chapitre suivant, on abordera les structures conditionnelles, permettant de diriger le flux d'instructions et la gestion des erreurs.

+ +

{{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Contrôle_du_flux_Gestion_des_erreurs")}}

diff --git a/files/fr/web/javascript/guide/utiliser_le_json_natif/index.html b/files/fr/web/javascript/guide/utiliser_le_json_natif/index.html new file mode 100644 index 0000000000..d8037999b8 --- /dev/null +++ b/files/fr/web/javascript/guide/utiliser_le_json_natif/index.html @@ -0,0 +1,99 @@ +--- +title: Utiliser le JSON natif +slug: Web/JavaScript/Guide/Utiliser_le_JSON_natif +tags: + - Add-ons + - Advanced + - ECMAScript5 + - Extensions + - JSON + - JavaScript +translation_of: Web/JavaScript/Reference/Global_Objects/JSON +--- +

{{jsSidebar("JavaScript Guide")}}

+ +

Cet article aborde l'objet JSON natif conforme à ECMAScript 5 qui a été ajouté à Gecko 1.9.1. Pour consulter les informations de base sur l'utilisation de JSON dans les versions précédentes de Firefox, consulter la page JSON.

+ +

L'objet natif JSON possède deux méthodes clés. La méthode JSON.parse() qui analyse une chaîne de caractères JSON et qui reconstruit l'objet JavaScript original. La méthode JSON.stringify(), quant à elle, accepte un objet JavaScript et renvoie son équivalent JSON.

+ +
Note : JSON ne supporte pas les structures cycliques. Toute tentative de conversion d'une telle structure renverra une exception TypeError.
+ +

Analyser (parser) les chaînes JSON

+ +

Afin de convertir une chaîne JSON en un objet JavaScript, il suffit de passer une chaîne JSON à la méthode JSON.parse() :

+ +
var objetJS = JSON.parse(chaineJSON);
+ +
+

À partir de JavaScript 1.8.5 (Firefox 4), JSON.parse() n'accepte pas les virgules en fin de chaîne

+
+ +
// ces deux instructions renverront une exception SyntaxError
+// à partir de JavaScript 1.8.5
+var objetJS = JSON.parse("[1, 2, 3, 4, ]");
+var objetJS = JSON.parse("{ \"toto\" : 1, }");
+
+ +

Convertir les objets en JSON

+ +

Afin de convertir un objet JavaScript en une chaîne JSON, il suffit de passer l'objet à la méthode JSON.stringify() :

+ +
var toto = {};
+toto.truc = "nouvelle propriété";
+toto.machin = 3;
+
+var chaineJSON = JSON.stringify(toto);
+
+ +

chaineJSON contient désormais '{"truc":"nouvelle propriété","machin":3}'.

+ +

Depuis Firefox 3.5.4, JSON.stringify() permet d'adapter la conversion grâce à des paramètres optionnels. La syntaxe est la suivante :

+ +

chaineJSON = JSON.stringify(valeur [, remplacement [, espace]])remplacement

+ +
+
valeur
+
L'objet JavaScript à convertir en une chaîne JSON.
+
remplacement
+
Une fonction qui modifie le comportement de la conversion ou bien un tableau d'objets String et Number qui sera utilisé comme une liste de propriétés de l'objet valeur à inclure dans la chaîne JSON. Si cette valeur est nulle ou n'est pas fournie, toutes les propriétés de l'objet seront inclues dans la chaîne résultante.
+
espace
+
Un objet String ou Number utilisé pour insérer des espaces dans la chaîne JSON afin qu'elle soit plus lisible. Si c'est un objet Number, il indique le nombre d'espaces à insérer. Ce nombre est limité à 10. Les valeurs inférieures à 1 indiquent qu'aucun espace ne sera utilisé, les valeurs supérieures à 10 seront ramenées à 10. Si cet objet est une String, la chaîne de caractères (ou les 10 premiers caractères si la chaîne est plus longue) à utiliser comme blanc. Si ce paramètre n'est pas fourni (ou vaut null), aucun blanc ne sera utilisé.
+
+ +

Le paramètre de remplacement

+ +

La paramètre remplacement peut être une fonction ou un tableau. Si c'est une fonction, elle prendra deux paramètres : la clé et la valeur à être convertie en chaîne de caractères. L'objet pour lequel la clé a été trouvée sera fourni comme paramètre this de la fonction de remplacement. Initialement elle est appelée avec une clé vide représentant l'objet à transformer en chaîne et est ensuite appelé pour chacune des propriétés de l'objet ou du tableau à convertir. Elle doit renvoyer la valeur à ajouter à la chaîne de caractère JSON comme suit :

+ + + +
Note : Il est impossible d'utiliser la fonction de remplacement pour retirer des valeurs d'un tableau. Si la valeur undefined ou une fonction est renvoyée  : null sera renvoyé.
+ +

Exemple

+ +
function censure(key, value) {
+  if (typeof value === "string") {
+    return undefined;
+  }
+  return value;
+}
+
+var toto = {fondation: "Mozilla", modèle: "box", semaine: 45, transport: "voiture", mois: 7};
+var chaineJSON = JSON.stringify(toto, censure);
+
+ +

La chaîne JSON produite sera {"semaine":45,"mois":7}.

+ +

Si remplacement est un tableau, les valeurs du tableau indiquent les noms des propriétés de l'objet à inclure dans la chaîne JSON.

+ +

Voir aussi

+ + diff --git a/files/fr/web/javascript/guide/utiliser_les_objets/index.html b/files/fr/web/javascript/guide/utiliser_les_objets/index.html new file mode 100644 index 0000000000..3879fd0b58 --- /dev/null +++ b/files/fr/web/javascript/guide/utiliser_les_objets/index.html @@ -0,0 +1,474 @@ +--- +title: Utiliser les objets +slug: Web/JavaScript/Guide/Utiliser_les_objets +tags: + - Débutant + - Guide + - JavaScript + - Object +translation_of: Web/JavaScript/Guide/Working_with_Objects +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Collections_avec_clés", "Web/JavaScript/Guide/Le_modèle_objet_JavaScript_en_détails")}}
+ +

JavaScript est conçu autour d'un paradigme simple, basé sur les objets. Un objet est un ensemble de propriétés et une propriété est une association entre un nom (aussi appelé clé) et une valeur. La valeur d'une propriété peut être une fonction, auquel cas la propriété peut être appelée « méthode ». En plus des objets natifs fournis par l'environnement, il est possible de construire ses propres objets. Ce chapitre aborde la manipulation d'objets, l'utilisation des propriétés, fonctions et méthodes, il explique également comment créer ses objets.

+ +

Un aperçu des objets

+ +

À l'instar de nombreux autres langages de programmation, on peut comparer les objets JavaScript aux objets du monde réel.

+ +

En JavaScript, un objet est une entité à part entière qui possède des propriétés. Si on effectue cette comparaison avec une tasse par exemple, on pourra dire qu'une tasse est un objet avec des propriétés. Ces propriétés pourront être la couleur, la forme, le poids, le matériau qui la constitue, etc. De la même façon, un objet JavaScript possède des propriétés, chacune définissant une caractéristique.

+ +

Les objets et les propriétés

+ +

Un objet JavaScript possède donc plusieurs propriétés qui lui sont associées. Une propriété peut être vue comme une variable attachée à l'objet. Les propriétés d'un objet sont des variables tout ce qu'il y a de plus classiques, exception faite qu'elle sont attachées à des objets. Les propriétés d'un objet représentent ses caractéristiques et on peut y accéder avec une notation utilisant le point « . », de la façon suivante :

+ +
nomObjet.nomPropriete
+
+ +

Comme pour les variables JavaScript en général, le nom de l'objet et le nom des propriétés sont sensibles à la casse (une lettre minuscule ne sera pas équivalente à une lettre majuscule). On peut définir une propriété en lui affectant une valeur. Ainsi, si on crée un objet maVoiture et qu'on lui donne les propriétés fabricant, modèle, et année :

+ +
var maVoiture = new Object();
+maVoiture.fabricant = "Ford";
+maVoiture.modèle = "Mustang";
+maVoiture.année = 1969;
+
+ +

Les propriétés d'un objet qui n'ont pas été affectées auront la valeur {{jsxref("undefined")}} (et non {{jsxref("null")}}).

+ +
maVoiture.sansPropriete; // undefined
+ +

On peut aussi définir ou accéder à des propriétés JavaScript en utilisant une notation avec les crochets (voir la page sur les accesseurs de propriétés pour plus de détails). Les objets sont parfois appelés « tableaux associatifs ». Cela peut se comprendre car chaque propriété est associée avec une chaîne de caractères qui permet d'y accéder. Ainsi, par exemple, on peut accéder aux propriétés de l'objet maVoiture de la façon suivante :

+ +
maVoiture["fabricant"] = "Ford";
+maVoiture["modèle"] = "Mustang";
+maVoiture["année"] = 1969;
+
+ +

Le nom d'une propriété d'un objet peut être n'importe quelle chaîne JavaScript valide (ou n'importe quelle valeur qui puisse être convertie en une chaîne de caractères), y compris la chaîne vide. Cependant, n'importe quel nom de propriété qui n'est pas un identifiant valide (par exemple si le nom d'une propriété contient un tiret, un espace ou débute par un chiffre) devra être utilisé avec la notation à crochets. Cette notation s'avère également utile quand les noms des propriétés sont déterminés de façon dynamique (c'est-à-dire qu'on ne sait pas le nom de la propriété avant l'exécution). Par exemple :

+ +
// on crée quatre variables avec une même instruction
+var monObj = new Object(),
+    str = "myString",
+    rand = Math.random(),
+    obj = new Object();
+
+monObj.type              = "Syntaxe point";
+monObj["date created"]   = "Chaîne avec un espace";
+monObj[str]              = "Une valeur qui est une chaîne";
+monObj[rand]             = "Nombre aléatoire";
+monObj[obj]              = "Objet";
+monObj[""]               = "Une chaîne vide";
+
+console.log(monObj);
+
+ +

On notera que les valeurs utilisées entre les crochets sont automatiquement converties en chaînes de caractères grâce à la méthode toString() sauf si ces valeurs sont des symboles (cf. {{jsxref("Symbol")}}). En effet, les noms des propriétés pour les objets JavaScript peuvent être des chaînes de caractères ou des symboles. Ainsi, dans l'exemple précédent, lorsqu'on ajoute la clé obj sur monObj, le moteur JavaScript appelle la méthode obj.toString() et utilise la chaîne de caractères renvoyée par cette méthode comme nom pour la propriété.

+ +

On peut également accéder aux propriétés d'un objet en utilisant une valeur qui est une chaîne de caractères enregistrée dans une variable :

+ +
var nomPropriété = "fabricant";
+maVoiture[nomPropriété] = "Ford";
+
+nomPropriété = "modèle";
+maVoiture[nomPropriété] = "Mustang";
+
+ +

La notation avec les crochets peut être utilisée dans une boucle for...in afin de parcourir les propriétés énumérables d'un objet. Pour illustrer comment cela fonctionne, on définit la fonction suivante qui affiche les propriétés d'un objet qu'on lui a passé en argument avec le nom associé :

+ +
function afficherProps(obj, nomObjet) {
+  var resultat = "";
+  for (var i in obj) {
+    if (obj.hasOwnProperty(i)) {
+        resultat += nomObjet + "." + i + " = " + obj[i] + "\n";
+    }
+  }
+  return resultat;
+}
+
+ +

Si on appelle la fonction avec afficherProps(maVoiture, "maVoiture"), cela affichera le contenu suivant dans la console :

+ +
maVoiture.fabricant = Ford
+maVoiture.modèle = Mustang
+maVoiture.année = 1969
+ +

Parcourir les propriétés d'un objet

+ +

À partir d'ECMAScript 5, il existe trois méthodes natives pour lister/parcourir les propriétés d'un objet :

+ + + +

Avant ECMAScript 5, il n'existait aucune méthode native pour lister l'ensemble des propriétés d'un objet. Cependant, on pouvait utiliser le code suivant pour y parvenir :

+ +
function listerToutesLesPropriétés(o){
+  var objectToInspect;
+  var result = [];
+
+  for(objectToInspect = o;
+      objectToInspect !== null;
+      objectToInspect = Object.getPrototypeOf(objectToInspect)){
+    result = result.concat(Object.getOwnPropertyNames(objectToInspect));
+  }
+  return result;
+}
+
+ +

Cela peut être utile pour révéler les propriétés « cachées » car leur nom est réutilisé dans la chaîne de prototypes. Pour lister les propriétés accessibles, il suffit de retirer les duplicatas du tableau.

+ +

Créer de nouveaux objets

+ +

Un environnement JavaScript possède certains objets natifs prédéfinis. En plus de ces objets, il est possible de créer ses propres objets. Pour cela, on peut utiliser un initialisateur d'objet. On peut aussi créer un constructeur puis instancier un objet avec cette fonction en utilisant l'opérateur new.

+ +

Utiliser les initialisateurs d'objets

+ +

On peut créer des objets avec une fonction qui est un constructeur mais on peut aussi créer des objets avec des initialisateurs d'objets. On appelle parfois cette syntaxe la notation littérale.

+ +

La syntaxe utilisée avec les initialisateurs d'objets est la suivante :

+ +
var obj = { propriete_1:   valeur_1,   // propriete_# peut être un identifiant
+            2:             valeur_2,   // ou un nombre
+            // ...,
+            "propriete n": valeur_n }; // ou une chaîne
+
+ +

où on a obj le nom de l'objet qu'on souhaite créer et chaque propriété_i un identifiant (que ce soit un nom, un nombre ou une chaîne de caractères) et chaque valeur_i une expression dont la valeur sera affectée à la propriété propriété_i. S'il n'est pas nécessaire d'utiliser l'objet obj par la suite, il n'est pas nécessaire de réaliser l'affectation à une variable (attention alors à l'encadrer dans des parenthèses pour que le littéral objet soit bien interprété comme une instruction et non pas comme un bloc.)

+ +

Les initialisateurs d'objets sont des expressions et chaque initialisateur entraîne la création d'un nouvel objet dans l'instruction pour laquelle il est exécuté. Des initialisateurs d'objets identiques créeront des objets distincts qui ne seront pas équivalents. Les objets sont créés de la même façon qu'avec new Object(), les objets créés à partir d'une expression littérale seront des instances d'Object.

+ +

L'instruction suivante crée un objet et l'affecte à une variable x si et seulement si l'expression cond est vraie :

+ +
if (cond) var x = {emplacement: "le monde"};
+
+ +

Dans l'exemple suivant, on crée un objet maHonda avec trois propriétés. La propriété moteur est également un objet avec ses propres propriétés.

+ +
var maHonda = {couleur: "rouge", roue: 4, moteur: {cylindres: 4, taille: 2.2}};
+
+ +

De la même façon, on pourra utiliser des initialisateurs pour créer des tableaux. Pour plus d'informations à ce sujet, voir les littéraux de tableaux.

+ +

Utiliser les constructeurs

+ +

On peut créer des objets d'une autre façon, en suivant deux étapes :

+ +
    +
  1. On définit une fonction qui sera un constructeur définissant le type de l'objet. La convention, pour nommer les constructeurs, est d'utiliser une majuscule comme première lettre pour l'identifiant de la fonction.
  2. +
  3. On crée une instance de l'objet avec new.
  4. +
+ +

Pour définir le type d'un objet, on crée une fonction qui définit le nom de ce type et les propriétés et méthodes des instances. Ainsi, si on souhaite créer un type d'objet pour représenter des voitures, on pourra nommer ce type voiture, et il pourra avoir des propriétés pour le fabricant, le modèle et l'année. Pour ce faire, on pourra écrire la fonction suivante :

+ +
function Voiture(fabricant, modèle, année) {
+  this.fabricant = fabricant;
+  this.modele = modele;
+  this.annee = annee;
+}
+
+ +

On voit ici qu'on utilise le mot-clé this pour affecter des valeurs aux propriétés d'un objet en fonction des valeurs passées en arguments de la fonction.

+ +

On peut désormais créer un objet maVoiture de la façon suivante :

+ +
var maVoiture = new Voiture("Eagle", "Talon TSi", 1993);
+
+ +

Cette instruction crée un objet maVoiture et lui affecte les valeurs fournies pour ses propriétés. On obtient donc maVoiture.fabricant qui sera la chaîne de caractères "Eagle", maVoiture.année qui sera l'entier 1993, et ainsi de suite.

+ +

Grâce à ce constructeur, on peut ensuite créer autant d'objets voiture que nécessaire. Par exemple :

+ +
var voitureMorgan = new Voiture("Audi", "A3", 2005);
+var voitureMax = new Voiture("Mazda", "Miata", 1990);
+
+ +

Un objet peut avoir une propriété qui est elle-même un objet. Ainsi, si on définit un type d'objet personne de cette façon :

+ +
function Personne(nom, âge, sexe) {
+  this.nom = nom;
+  this.age = age;
+  this.sexe = sexe;
+}
+
+ +

et qu'on instancie deux nouveaux objets personne avec

+ +
var max = new Personne("Max Gun", 33, "M");
+var morguy = new Personne("Morgan Sousbrouille", 39, "M");
+
+ +

On pourra réécrire la fonction de définition pour le type voiture pour inclure une propriété propriétaire qui est représentée par un objet personne :

+ +
function Voiture(fabricant, modèle, année, propriétaire) {
+  this.fabricant = fabricant;
+  this.modele = modele;
+  this.annee = annee;
+  this.propriétaire = propriétaire;
+}
+
+ +

Pour instancier des nouveaux objets, on pourra donc utiliser :

+ +
var voiture1 = new Voiture("Mazda", "Miata", 1993, max);
+var voiture2 = new Voiture("Audi", "A3", 2005, morguy);
+
+ +

On notera que le dernier argument n'est pas une chaîne de caractères ou une valeur numérique mais bien un objet. Les objets max et morguy sont passés en arguments pour représenter les propriétaires. Ainsi, si on veut obtenir le nom du propriétaire pour voiture2, on peut accéder à la propriété de la façon suivante :

+ +
voiture2.propriétaire.nom
+
+ +

Il est toujours possible d'ajouter une propriété à un objet défini précédemment. Par exemple, on peut ajouter une propriété à l'objet voiture1 avec l'instruction :

+ +
voiture1.couleur = "noir";
+
+ +

Ici, on ajoute une propriété couleur à voiture1, et on lui affecte une valeur "noir". Cependant, cela n'affecte pas les autres objets voiture. Pour ajouter une nouvelle propriété à tous les objets, il faudra ajouter la propriété au constructeur voiture.

+ +

Utiliser la méthode Object.create()

+ +

Les objets peuvent également être créés en utilisant la méthode {{jsxref("Object.create()")}}. Cette méthode peut s'avérer très utile car elle permet de choisir le prototype pour l'objet qu'on souhaite créer, sans avoir à définir un constructeur.

+ +
// Propriétés pour animal et encapsulation des méthodes
+var Animal = {
+  type: "Invertébrés",        // Valeur par défaut  value of properties
+  afficherType : function() {  // Une méthode pour afficher le type Animal
+    console.log(this.type);
+  }
+}
+
+// On crée un nouveau type d'animal, animal1
+var animal1 = Object.create(Animal);
+animal1.afficherType(); // affichera Invertébrés
+
+// On crée un type d'animal "Poisson"
+var poisson = Object.create(Animal);
+poisson.type = "Poisson";
+poisson.afficherType(); // affichera Poisson
+ +

L'héritage

+ +

Tous les objets JavaScript héritent d'un autre objet. L'objet dont on hérite est appelé prototype et les propriétés héritées peuvent être accédées via l'objet prototype du constructeur. Pour plus d'informations sur le fonctionnement de l'héritage, voir la page sur l'héritage et la chaîne de prototypes.

+ +

Indexer les propriétés d'un objet

+ +

Il est possible d'accéder à une propriété via son nom et via son indice (ordinal). Si on définit une propriété grâce à un nom, on accédera toujours à la valeur via le nom. De même, si on définit une propriété grâce à un indice, on y accèdera toujours via son indice.

+ +

Cette restriction s'applique lorsqu'on crée un objet et ses propriétés via un constructeur et lorsqu'on déclare les propriétés explicitement (par exemple avec maVoiture.couleur = "rouge"). Si on définit une propriété d'un objet avec maVoiture[5] = "25 kmh", on pourra faire référence à cette propriété grâce à maVoiture[5].

+ +

Il existe une exception à cette règle lorsqu'on manipule des objets "semblables à des tableaux" provenant d'API Web telles que l'objet forms. Pour ces objets semblables à des tableaux, on peut accéder à une propriété de l'objet grâce à son nom (si l'attribut {{htmlattrxref("name")}} est utilisé sur l'élément HTML) ou grâce à son index selon l'ordre dans le document. Ainsi, si on souhaite cibler un élément <form> du document possédant un attribut name qui vaut monForm et que cet élément est le deuxième élément du document, on pourra y accéder avec document.forms[1], document.forms["monForm"] ou encore avec document.forms.monForm.

+ +

Définir des propriétés pour un type d'objet

+ +

On peut ajouter une propriété à un type précédemment défini en utilisant la propriété prototype. Cela permettra de définir une propriété qui sera partagée par tous les objets d'un même type plutôt qu'elle ne soit définie que pour un seul objet. Le code suivant permet d'ajouter une propriété couleur à tous les objets de type voiture. On affecte ensuite une valeur à cette propriété pour l'objet voiture1.

+ +
Voiture.prototype.couleur = null;
+voiture1.couleur = "noir";
+
+ +

Pour plus d'informations, voir l'article sur la propriété prototype de l'objet Function de la référence JavaScript.

+ +

Définir des méthodes

+ +

Une méthode est une fonction associée à un objet. Autrement dit, une méthode est une propriété d'un objet qui est une fonction. Les méthodes sont définies comme des fonctions normales et sont affectées à des propriétés d'un objet. Voir la page sur les définitions de méthodes pour plus d'informations. Par exemple :

+ +
nomObjet.nomMéthode = nomFonction;
+
+var monObj = {
+  maMéthode: function(params) {
+    // ...faire quelque chose
+  }
+};
+
+ +

avec nomObjet qui est un objet existant, nomMéthode est le nom de la propriété à laquelle on souhaite affecter la méthode et nomFonction le nom de la fonction.

+ +

On peut ensuite appeler la méthode sur l'objet :

+ +
object.nomMéthode(paramètres);
+
+ +

On peut définir des méthodes pour un type d'objet en incluant la définition de la méthode dans le constructeur. Par exemple, on peut définir une fonction qui mettrait en forme et qui afficherait les propriétés d'un objet voiture. Par exemple :

+ +
function afficheVoiture() {
+  var résultat = "Une " + this.fabricant + " " + this.modèle
+    + " de cette année " + this.année;
+  console.log(résultat);
+}
+
+ +

On peut ensuite ajouter cette fonction comme méthode dans le constructeur avec cette instruction :

+ +
this.afficheVoiture = afficheVoiture;
+
+ +

La définition complète serait donc :

+ +
function Voiture(fabricant, modèle, année, propriétaire) {
+  this.fabricant = fabricant;
+  this.modèle = modèle;
+  this.année = année;
+  this.propriétaire = propriétaire;
+  this.afficheVoiture = afficheVoiture;
+}
+
+ +

On pourra donc ensuite appeler la méthode afficheVoiture pour chaque objet de ce type :

+ +
voiture1.afficheVoiture();
+voiture2.afficheVoiture();
+
+ +

Utiliser this

+ +

JavaScript possède un mot-clé spécial this, qui peut être utiliser à l'intérieur d'une méthode pour faire référence à l'objet courant. Par exemple, si on a une fonction valider qui permet de valider la propriété valeur d'un objet en fonction d'un seuil minimum et d'un seuil maximum :

+ +
function valider(obj, seuilMin, seuilMax) {
+  if ((obj.value < seuilMin) || (obj.value > seuilMax))
+    console.log("Valeur invalide !");
+}
+
+ +

Cette fonction pourrait ensuite être appelée via le gestionnaire d'événement onchange pour les éléments d'un formulaire et la valeur pour l'élément du formulaire serait passée en argument :

+ +
<input type="text" name="âge" size="3"
+  onchange="valider(this, 18, 99)">
+ +

En général, this fait référence à l'objet appelant de la méthode.

+ +

Définir des accesseurs et des mutateurs (getters et setters)

+ +

Un accesseur (getter) est une méthode qui permet de récupérer la valeur d'une propriété donnée. Un mutateur (setter) est une méthode qui permet de définir la valeur d'une propriété donnée. Il est possible de définir des accesseurs et des mutateurs sur chaque objet (qu'il soit natif ou défini par l'utilisateur) qui supporte l'ajout de nouvelles propriétés. La syntaxe pour définir les accesseurs et mutateurs utilise les littéraux objets.

+ +

Dans l'exemple suivant, on ajoute des accesseurs et mutateurs à un objet existant o.

+ +
var o = {
+  a: 7,
+  get b() {
+    return this.a + 1;
+  },
+  set c(x) {
+    this.a = x / 2
+  }
+};
+
+console.log(o.a); // 7
+console.log(o.b); // 8
+o.c = 50;
+console.log(o.a); // 25
+
+ +

Les propriétés de l'objet o sont :

+ + + +

Pour utiliser une fonction déjà existante et la définir comme accesseur ou mutateur d'un objet, on pourra utiliser la méthode Object.defineProperty() (ou l'ancienne méthode Object.prototype.__defineGetter__).

+ +

Le code suivant illustre comment étendre le prototype {{jsxref("Date")}} avec des accesseurs et mutateurs afin d'ajouter une propriété année pour toutes les instances du type Date. Pour cela, on utilise les méthodes de Date getFullYear et setFullYear :

+ +
var d = Date.prototype;
+Object.defineProperty(d, "année", {
+  get: function() { return this.getFullYear() },
+  set: function(y) { this.setFullYear(y) }
+});
+
+ +

Ces instructions utilisent l'accesseur et le mutateur pour un objet Date :

+ +
var ajd = new Date();
+console.log(ajd.année); // 2000
+ajd.année = 2001; // 987617605170
+console.log(ajd);
+// Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
+
+ +

En général, les accesseurs et mutateurs peuvent être :

+ + + +

Lorsqu'on définit des accesseurs et des mutateurs avec des littéraux objets, il suffit de préfixer un accesseur par get et un mutateur par set. Bien entendu, la méthode pour l'accesseur nécessite aucun paramètre et le mutateur attend exactement un paramètre (la nouvelle valeur à définir). Par exemple :

+ +
var o = {
+  a: 7,
+  get b() { return this.a + 1; },
+  set c(x) { this.a = x / 2; }
+};
+
+ +

On peut aussi ajouter des accesseurs et des mutateurs par la suite (après la création de l'objet) avec la méthode Object.defineProperties. Le premier argument de cette méthode est l'objet sur lequel on souhaite ajouter des propriétés. Le second argument est un objet qui représente les propriétés à ajouter (ici les mutateurs et accesseurs). Voici un exemple pour lequel on définit les mêmes accesseurs et mutateurs que précédemment :

+ +
var o = { a:0 }
+
+Object.defineProperties(o, {
+    "b": { get: function () { return this.a + 1; } },
+    "c": { set: function (x) { this.a = x / 2; } }
+});
+
+o.c = 10 // Lance le mutateur qui affecte 10 / 2 (5) à 'a'
+console.log(o.b) // Lance l'accesseur qui affiche a + 1 donc 6
+
+ +

Selon le résultat qu'on souhaite obtenir, on utilisera l'une des deux formes. Si on connait bien la structure de l'objet lorsqu'on le définit, on les ajoutera au constructeur. Si on utilise des éléments dynamiques et que la structure de l'objet évolue, on utilisera la deuxième façon.

+ +

Supprimer des propriétés

+ +

Il est possible de retirer des propriétés propres (celles qui ne sont pas héritées) grâce à l'opérateur delete. Le code suivant montre comment retirer une propriété :

+ +
// On crée un nouvel objet, monObj, avec deux propriétés a et b.
+var monObj = new Object;
+monObj.a = 5;
+monObj.b = 12;
+
+// On retire la propriété a, monObj a donc uniquement la propriété b
+delete monObj.a;
+console.log("a" in monObj) // produit "false"
+
+ +

Il est aussi possible de supprimer une propriété de l'objet global avec delete si le mot-clé var n'avait pas été utilisé :

+ +
g = 17;
+delete g;
+
+ +

Comparer des objets

+ +

En JavaScript, les objets fonctionnent par référence. Deux objets distincts ne sont jamais égaux, même s'ils ont les mêmes valeurs pour les mêmes propriétés. On aura une équivalence uniquement si on compare un objet avec lui-même.

+ +
// Deux variables avec deux objets distincts qui ont les mêmes propriétés
+var fruit = {nom: "pomme"};
+var fruit2 = {nom: "pomme"};
+
+fruit == fruit2  // return false
+fruit === fruit2 // return false
+ +
// Deux variables avec un même objet
+var fruit = {nom: "pomme"};
+var fruit2 = fruit;  // On affecte la même référence
+
+// dans ce cas fruit et fruit2 pointent vers le même objet
+fruit == fruit2  // return true
+fruit === fruit2 // return true
+
+fruit.nom = "raisin";
+console.log(fruit2); // affiche {nom: "raisin"} et non {nom: "pomme"}
+
+ +

Pour plus d'informations sur les opérateurs de comparaisons, voir cet article.

+ +

Voir aussi

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Collections_avec_clés", "Web/JavaScript/Guide/Le_modèle_objet_JavaScript_en_détails")}}

diff --git a/files/fr/web/javascript/guide/utiliser_les_promesses/index.html b/files/fr/web/javascript/guide/utiliser_les_promesses/index.html new file mode 100644 index 0000000000..2198201957 --- /dev/null +++ b/files/fr/web/javascript/guide/utiliser_les_promesses/index.html @@ -0,0 +1,314 @@ +--- +title: Utiliser les promesses +slug: Web/JavaScript/Guide/Utiliser_les_promesses +tags: + - Guide + - Intermédiaire + - JavaScript + - Promesses + - Promise +translation_of: Web/JavaScript/Guide/Using_promises +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Le_modèle_objet_JavaScript_en_détails", "Web/JavaScript/Guide/iterateurs_et_generateurs")}}
+ +

Une promesse est un objet ({{jsxref("Promise")}}) qui représente la complétion ou l'échec d'une opération asynchrone. La plupart du temps, on « consomme » des promesses et c'est donc ce que nous verrons dans la première partie de ce guide pour ensuite expliquer comment les créer.

+ +

En résumé, une promesse est un objet qui est renvoyé et auquel on attache des callbacks plutôt que de passer des callbacks à une fonction. Ainsi, au lieu d'avoir une fonction qui prend deux callbacks en arguments :

+ +
function faireQqcALAncienne(successCallback, failureCallback){
+  console.log("C'est fait");
+  // réussir une fois sur deux
+  if (Math.random() > .5) {
+    successCallback("Réussite");
+  } else {
+    failureCallback("Échec");
+  }
+}
+
+function successCallback(résultat) {
+  console.log("L'opération a réussi avec le message : " + résultat);
+}
+
+
+function failureCallback(erreur) {
+  console.error("L'opération a échoué avec le message : " + erreur);
+}
+
+faireQqcALAncienne(successCallback, failureCallback);
+
+
+ +

On aura une fonction qui renvoie une promesse et on attachera les callbacks sur cette promesse :

+ +
function faireQqc() {
+  return new Promise((successCallback, failureCallback) => {
+    console.log("C'est fait");
+    // réussir une fois sur deux
+    if (Math.random() > .5) {
+      successCallback("Réussite");
+    } else {
+      failureCallback("Échec");
+    }
+  })
+}
+
+const promise = faireQqc();
+promise.then(successCallback, failureCallback);
+
+ +

ou encore :

+ +
faireQqc().then(successCallback, failureCallback);
+
+ +

Cette dernière forme est ce qu'on appelle un appel de fonction asynchrone. Cette convention possède différents avantages dont le premier est le chaînage.

+ +

Garanties

+ +

À la différence des imbrications de callbacks, une promesse apporte certaines garanties :

+ + + +

Chaînage des promesses

+ +

Un besoin fréquent est d'exécuter deux ou plus d'opérations asynchrones les unes à la suite des autres, avec chaque opération qui démarre lorsque la précédente a réussi et en utilisant le résultat de l'étape précédente. Ceci peut être réalisé en créant une chaîne de promesses.

+ +

La méthode then() renvoie une nouvelle promesse, différente de la première :

+ +
const promise = faireQqc();
+const promise2 = promise.then(successCallback, failureCallback);
+
+ +

ou encore :

+ +
const promise2 = faireQqc().then(successCallback, failureCallback);
+
+ +

La deuxième promesse (promise2) indique l'état de complétion, pas uniquement pour faireQqc() mais aussi pour le callback qui lui a été passé (successCallback ou failureCallback) qui peut aussi être une fonction asynchrone qui renvoie une promesse. Lorsque c'est le cas, tous les callbacks ajoutés à promise2 forment une file derrière la promesse renvoyée par successCallback ou failureCallback.

+ +

Autrement dit, chaque promesse représente l'état de complétion d'une étape asynchrone au sein de cette succession d'étapes.

+ +

Auparavant, l'enchaînement de plusieurs opérations asynchrones déclenchait une pyramide dantesque de callbacks :

+ +
faireQqc(function(result) {
+  faireAutreChose(result, function(newResult) {
+    faireUnTroisiemeTruc(newResult, function(finalResult) {
+      console.log('Résultat final :' + finalResult);
+    }, failureCallback);
+  }, failureCallback);
+}, failureCallback);
+
+ +

Grâce à des fonctions plus modernes et aux promesses, on attache les callbacks aux promesses qui sont renvoyées. On peut ainsi construire une chaîne de promesses :

+ +
faireQqc().then(function(result) {
+  return faireAutreChose(result);
+})
+.then(function(newResult) {
+  return faireUnTroisiemeTruc(newResult);
+})
+.then(function(finalResult) {
+  console.log('Résultat final : ' + finalResult);
+})
+.catch(failureCallback);
+
+ +

Les arguments passés à then sont optionnels. La forme catch(failureCallback) est un alias plus court pour then(null, failureCallback). Ces chaînes de promesses sont parfois construites avec des fonctions fléchées :

+ +
faireQqc()
+.then(result => faireAutreChose(result))
+.then(newResult => faireUnTroisiemeTruc(newResult))
+.then(finalResult => {
+  console.log('Résultat final : ' + finalResult);
+})
+.catch(failureCallback);
+
+ +
+

Important : cela implique que les fonctions asynchrones renvoient toutes des promesses, sinon les callbacks ne pourront être chaînés et les erreurs ne seront pas interceptées (les fonctions fléchées ont une valeur de retour implicite si les accolades ne sont pas utilisées : () => x est synonyme de () => { return x; }).

+
+ +

Chaînage après un catch

+ +

Il est possible de chaîner de nouvelles actions après un rejet, c'est-à-dire un catch. C'est utile pour accomplir de nouvelles actions après qu'une action ait échoué dans la chaine. Par exemple :

+ +
new Promise((resolve, reject) => {
+    console.log('Initial');
+
+    resolve();
+})
+.then(() => {
+    throw new Error('Something failed');
+
+    console.log('Do this');
+})
+.catch(() => {
+    console.error('Do that');
+})
+.then(() => {
+    console.log('Do this whatever happened before');
+});
+
+ +

Cela va produire la sortie suivante :

+ +
Initial
+Do that
+Do this whatever happened before
+
+ +

Notez que le texte Do this n'est pas affiché car l'erreur Something failed a produit un rejet.

+ +

Propagation des erreurs

+ +

Dans les exemples précédents, failureCallback était présent trois fois dans la pyramide de callbacks et une seule fois, à la fin, dans la chaîne des promesses :

+ +
faireQqc()
+.then(result => faireAutreChose(result))
+.then(newResult => faireUnTroisiemeTruc(newResult))
+.then(finalResult => console.log('Résultat final : ' + finalResult))
+.catch(failureCallback);
+
+ +

En fait, dès qu'une exception est levée, la chaîne de promesses utilisera le premier catch() ou onRejected disponible. Ce fonctionnement est assez proche de ce qu'on peut trouver pour du code synchrone :

+ +
try {
+  const result = syncFaireQqc();
+  const newResult = syncFaireQqcAutre(result);
+  const finalResult = syncFaireUnTroisiemeTruc(newResult);
+  console.log('Résultat final : ' + finalResult);
+} catch(error) {
+  failureCallback(error);
+}
+
+ +

Cette symétrie entre le code asynchrone et le code synchrone atteint son paroxysme avec le couple d'opérateurs async/await d'ECMAScript 2017:

+ +
async function toto() {
+  try {
+    const result = await faireQqc();
+    const newResult = await faireQqcAutre(result);
+    const finalResult = await faireUnTroisiemeTruc(newResult);
+    console.log('Résultat final : ' + finalResult);
+  } catch(error) {
+    failureCallback(error);
+  }
+}
+
+ +

Ce fonctionnement est construit sur les promesses et faireQqc() est la même fonction que celle utilisée dans les exemples précédents.

+ +

Les promesses permettent de résoudre les problèmes de cascades infernales de callbacks notamment en interceptant les différentes erreurs (exceptions et erreurs de programmation). Ceci est essentiel pour obtenir une composition fonctionnelle des opérations asynchrones.

+ +

Évènements liés à la rupture d'une promesse

+ +

Lorsqu'une promesse est rompue/rejetée, un des deux évènements suivants est envoyé au niveau de la portée globale ({{domxref("window")}} ou {{domxref("Worker")}} si le script est utilisé dans un worker) :

+ +
+
{{domxref("Window.rejectionhandled_event","rejectionhandled")}}
+
Cet évènement est envoyé lorsqu'une promesse est rompue et après que le rejet ai été traité par la fonction reject associée à la promesse.
+
{{domxref("Window.unhandledrejection_event","unhandledrejection")}}
+
Cet évènement est envoyé lorsque la promesse est rompue et qu'aucune fonction n'a été définie pour gérer le rejet de la promesse.
+
+ +

Dans les deux cas, l'évènement (dont le type est {{domxref("PromiseRejectionEvent")}}) aura deux propriétés :

+ +
+
{{domxref("PromiseRejectionEvent.promise","promise")}}
+
La promesse qui a été rompue.
+
{{domxref("PromiseRejectionEvent.reason","reason")}}
+
La raison pour laquelle la promesse a été rompue.
+
+ +

Gérer ces évènements permet d'avoir une ultime méthode pour gérer le rejet des promesses. Cela peut notamment s'avérer utile pour le débogage. Ces évènements sont déclenchés au niveau global et permettent ainsi d'intercepter les erreurs pour chaque contexte (fenêtre ou worker)

+ +
window.addEventListener("unhandledrejection", event => {
+  // Examiner la ou les promesse(s) qui posent problème en debug
+  // Nettoyer ce qui doit l'être quand ça se produit en réel
+
+}, false);
+ +

Envelopper les callbacks des API

+ +

Il est possible de créer un objet  {{jsxref("Promise")}} grâce à son constructeur. Et même si, idéalement, cela ne devrait pas être nécessaire, certaines API fonctionnent toujours avec des callbacks passés en arguments. C'est notamment le cas de la méthode  {{domxref("WindowTimers.setTimeout", "setTimeout()")}} :

+ +
setTimeout(() => saySomething("10 seconds passed"), 10 * 1000);
+
+ +

Si on mélange des callbacks et des promesses, cela sera problématique. Si  saySomething échoue ou contient des erreurs, rien n'interceptera l'erreur.

+ +

Pour ces fonctions, la meilleure pratique consiste à les envelopper dans des promesses au plus bas niveau possible et de ne plus les appeler directement :

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait(10 * 1000).then(() => saySomething("10 seconds")).catch(failureCallback);
+
+ +

Le constructeur Promise prend en argument une fonction et nous permet de la convertir manuellement en une promesse. Ici, vu que setTimeout n'échoue pas vraiment, on laisse de côté la gestion de l'échec.

+ +

Composition

+ +

{{jsxref("Promise.resolve()")}} et {{jsxref("Promise.reject()")}} sont des méthodes qui permettent de créer des promesses déjà tenues ou rompues.

+ +

{{jsxref("Promise.all()")}} et {{jsxref("Promise.race()")}} sont deux outils de composition qui permettent de mener des opérations asynchrones en parallèle.

+ +

On peut lancer des opérations en parallèles et attendre qu'elles soient toutes finies de cette façon :

+ +
Promise.all([func1(), func2(), func3()])
+.then(([resultat1, resultat2, resultat3]) => { /* où on utilise resultat1/2/3 */ });
+ +

Il est possible de construire une composition séquentielle de la façon suivante :

+ +
[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());
+
+ +

Dans ce fragment de code, on réduit un tableau de fonctions asynchrones en une chaîne de promesse équivalente à : Promise.resolve().then(func1).then(func2);

+ +

On peut également accomplir cela avec une fonction de composition réutilisable  :

+ +
const applyAsync = (acc, val) => acc.then(val);
+const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
+ +

La fonction composeAsync accepte autant de fonctions que nécessaire comme arguments et renvoie une nouvelle fonction qui prend une valeur initiale pour la passer à travers ces étapes de compositions. Cette façon de faire garantit que les fonctions, qu'elles soient synchrones ou asynchrones, sont exécutées dans le bon ordre :

+ +
const transformData = composeAsync(func1, asyncFunc1, asyncFunc2, func2);
+transformData(data);
+ +

Avec ECMAScript 2017, on peut obtenir une composition séquentielle plus simplement avec les opérateurs await/async :

+ +
let result;
+for(const f of [func1, func2, func3]) {
+  result = await f(result);
+} 
+ +

Gestion du temps

+ +

Pour éviter de mauvaises surprises, les fonctions passées à then() ne seront jamais appelées de façon synchrone, y compris lorsqu'il s'agit d'une promesse déjà résolue :

+ +
Promise.resolve().then(() => console.log(2));
+console.log(1); // 1, 2
+
+ +

En fait, la fonction passée à then() est placée dans une file de micro-tâches qui sont exécutées lorsque cette file est vidée à la fin de la boucle d'évènements JavaScript :

+ +
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait().then(() => console.log(4));
+Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
+console.log(1); // 1, 2, 3, 4
+
+ +

Voir aussi

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Le_modèle_objet_JavaScript_en_détails", "Web/JavaScript/Guide/iterateurs_et_generateurs")}}

diff --git "a/files/fr/web/javascript/guide/\303\251galit\303\251_en_javascript/index.html" "b/files/fr/web/javascript/guide/\303\251galit\303\251_en_javascript/index.html" new file mode 100644 index 0000000000..782e52f907 --- /dev/null +++ "b/files/fr/web/javascript/guide/\303\251galit\303\251_en_javascript/index.html" @@ -0,0 +1,264 @@ +--- +title: L'égalité en JavaScript +slug: Web/JavaScript/Guide/Égalité_en_JavaScript +tags: + - Advanced + - Guide + - JavaScript + - Operators +translation_of: Web/JavaScript/Equality_comparisons_and_sameness +--- +

{{jsSidebar("JavaScript Guide")}}

+

EcmaScript6 possède trois outils pour déterminer si deux valeurs x et y sont « égales ».  Il y a l'égalité simple (deux signes égal) (==), l'égalité stricte (trois signes égal) (===), et la méthode Object.is. (Cette méthode a été ajoutée avec ES6. Les opérateurs d'égalité simple et stricte étaient présents en JavaScript avant ES6 et ont conservé leur comportement.)

+

Un aperçu

+

Voici comment utiliser chacun de ces outils de comparaisons :

+
x == y
+
x === y
+
Object.is(x, y)
+

En résumé : l'opérateur d'égalité simple effectuera une conversion de type entre les objets comparés, l'opérateur d'égalité stricte n'effectuera pas de conversion avant de comparer les objets (false est renvoyé automatiquement si les types sont différents), enfin Object.is se comportera de la même façon que l'opérateur d'égalité stricte avec des règles supplémentaires pour les valeurs NaN, -0 et +0. Object.is(-0, +0) ne sera pas vérifié et Object.is(NaN, NaN) sera vrai. (Généralement, quand on compare NaN et NaN, on obtient le résultat false car la norme IEEE 754 indique que ce comportement est celui attendu pour l'égalité simple ou stricte.)

+

Cette égalité ne s'applique qu'aux types de données primitifs, aucune des méthodes présentées ci-avant ne permet de comparer la structure de deux objets. Si deux objets x et y possèdent la même structure mais que ce sont des objets distincts, chacune de ces méthodes renverra le résultat false.

+

Ainsi :

+
let x = { valeur: 17 };
+let y = { valeur: 17 };
+console.log(Object.is(x, y)); // false;
+console.log(x === y);         // false
+console.log(x == y);          // false
+

Les égalités simples, strictes et les valeurs identiques

+

Les comparaisons effectuées par les opérateurs d'égalité simple et d'égalité stricte sont décrites par EcmaScript5 : l'algorithme de l'opérateur == est décrit dans la section 11.9.3 (en anglais) et l'algorithme de l'opérateur === est décrit dans la section 11.9.6 (en anglais). Ces deux algorithmes sont expliqués de façon simple et concise, il est préferable de lire le deuxième algorithme avant le premier. ES5 décrit également l'algorithme utilisé en interne par le moteur JavaScript : section 9.12, The SameValue Algorithm (en anglais). Ce dernier algorithme est très proche de celui utilisé pour l'égalité stricte, ils différent de par leurs gestions différentes des nombres représentés sous forme d'objets Number. Object.is n'est que la retranscription de cet algorithme, utilisable depuis ES6.

+

Excepté pour la conversion implicite, on peut voir que, pour les opérateurs d'égalité simple et stricte, l'algorithme d'égalité stricte est un sous-ensemble de l'égalité simple car 11.9.6.2-7 correspond à 11.9.3.1.a-f.

+

Comprendre le sens des différentes égalités

+

Avant ES6, on pouvait penser que l'égalité stricte était une version « améliorée » de l'égalité simple, ou vice-versa. Par exemple, dans certains cas, on peut trouver que l'égalité simple est plus souple que l'égalité stricte car elle effectue une conversion des types (ce qui permet de vérifier 6 == "6"). Au contraire, on peut trouver que l'égalité stricte est « meilleure » que l'égalité simple car il est nécessaire que les deux opérandes soient du même type. L'utilité de chaque opérateur dépend du cadre dans lequel on l'utilise.

+

Object.is, en revanche, n'est pas plus souple ou plus stricte que ces égalités. Il n'est pas non plus un « intermédiaire » entre ces deux opérateurs. Object.is diffère dans sa façon de gérer la valeur numérique spéciale NaN. D'une certaine façon, Object.is se différencie en fonction de ses caractéristiques spéciales sur NaN et -0 et +0.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Opérateurs d'égalité
xy=====Object.is
undefinedundefinedtruetruetrue
nullnulltruetruetrue
truetruetruetruetrue
falsefalsetruetruetrue
"toto""toto"truetruetrue
{ toto: "truc" }xtruetruetrue
00truetruetrue
+0-0truetruefalse
0falsetruefalsefalse
""falsetruefalsefalse
""0truefalsefalse
"0"0truefalsefalse
"17"17truefalsefalse
new String("toto")"toto"truefalsefalse
nullundefinedtruefalsefalse
nullfalsefalsefalsefalse
undefinedfalsefalsefalsefalse
{ toto: "truc" }{ toto: "truc" }falsefalsefalse
new String("toto")new String("toto")falsefalsefalse
0nullfalsefalsefalse
0NaNfalsefalsefalse
"toto"NaNfalsefalsefalse
NaNNaNfalsefalsetrue
+

Dans quels cas utiliser Object.is ou l'opérateur d'égalité stricte

+

En dehors du traîtement effectué pour NaN, Object.is s'avère utile lorsqu'on manipule des valeurs très proches de 0 (parfois utilisées pour la métaprogrammation et notamment pour les descripteurs de propriétés et qu'on souhaite reproduire certaines caractéristiques de Object.defineProperty). Si on n'a pas ce cas de figure à gérer, il est conseillé d'utiliser ===. Même dans l'éventualité où on devrait gérer une comparaison entre deux valeurs NaN il est souvent plus facile de traiter le cas particulier en utilisant la fonction isNaN présente dans les anciennes versions d'ECMAScript.

+

Voici une liste (non exhaustive) des méthodes et opérateurs qui pourraient entraîner une apparition des valeurs -0 et +0 :

+
+
+ - (négation unaire)
+
+
+
+

Il peut sembler évident que l'opposé de 0 est -0 mais lorsque que cette opération est réalisée dans une expression, il est plus facile d'identifier la transformation qui s'est effectuée. Par exemple :

+
let forceFrottement = obj.masse * -obj.vitesse
+

Si obj.vitesse vaut 0, on aura -0 comme résultat du calcul, et c'est cette valeur qui sera assignée à forceFrottement

+
+
+
+
+ Math.atan2
+
+ Math.ceil
+
+ Math.pow
+
+ Math.round
+
+
+
+ La valeur -0 peut être produite par ces méthodes (et donc introduite dans une expression qui les comportent), même dans le cas où -0 n'est pas un argument. Par exemple, si on utilise Math.pow pour calculer -Infinity à une puissance entière impaire et négative, on obtiendra -0. Voir les différentes pages sur ces méthodes pour plus d'informations.
+
+
+
+ Math.floor
+
+ Math.max
+
+ Math.min
+
+ Math.sin
+
+ Math.sqrt
+
+ Math.tan
+
+
+
+ Ces méthodes peuvent produire la valeur -0 si c'est un des paramètres de la fonction. Par exemple, Math.min(-0, +0) vaudra -0. Voir les différentes pages sur ces méthodes pour plus d'informations.
+
+
+
+ ~
+
+ <<
+
+ >>
+
+ Chacun de ces opérateurs utilise l'algorithme ToInt32. Or, il n'y a qu'une seule représentation possible pour 0 sous forme d'un entier sur 32 bits, c'est pourquoi -0 ne pourra pas être « conservé » par une combinaison de ces opérations (même si cette combinaison est équivalente, logiquement, à une identité). Par exemple Object.is(~~(-0), -0) et Object.is(-0 << 2 >> 2, -0) produiront la valeur false.
+
+

Il peut être dangereux d'utiliser Object.is quand on ne souhaite pas différencier les deux valeurs -0 et +0. En revanche, si on souhaite distinguer ces deux valeurs, cette fonction est idéale.

-- cgit v1.2.3-54-g00ecf