diff options
Diffstat (limited to 'files/fr/web/javascript/a_re-introduction_to_javascript')
-rw-r--r-- | files/fr/web/javascript/a_re-introduction_to_javascript/index.html | 931 |
1 files changed, 451 insertions, 480 deletions
diff --git a/files/fr/web/javascript/a_re-introduction_to_javascript/index.html b/files/fr/web/javascript/a_re-introduction_to_javascript/index.html index 7f9c63f5e6..eaa5596c8c 100644 --- a/files/fr/web/javascript/a_re-introduction_to_javascript/index.html +++ b/files/fr/web/javascript/a_re-introduction_to_javascript/index.html @@ -2,274 +2,276 @@ title: Une réintroduction à JavaScript slug: Web/JavaScript/A_re-introduction_to_JavaScript tags: + - CodingScripting + - Guide - Intermediate + - Intro - JavaScript - - Tutorial + - Learn translation_of: Web/JavaScript/A_re-introduction_to_JavaScript original_slug: Web/JavaScript/Une_réintroduction_à_JavaScript --- <div>{{jsSidebar}}</div> -<h2 id="Introduction">Introduction</h2> - -<p>Pourquoi une réintroduction ? Parce que JavaScript peut raisonnablement se targuer d'être <a class="external" href="http://crockford.com/javascript/javascript.html">le langage de programmation le plus incompris au monde</a>. Bien que souvent raillé comme étant un simple jouet, derrière sa simplicité désarmante se cachent certaines fonctionnalités de langage très puissantes. De nombreuses applications JavaScript de premier plan sont apparues, ce qui montre qu'une connaissance approfondie de cette technologie est une compétence importante pour tout développeur Web.</p> +<p>Pourquoi une réintroduction ? Parce que JavaScript peut raisonnablement se targuer d'être <a href="http://crockford.com/javascript/javascript.html">le langage de programmation le plus incompris au monde</a>. Bien que souvent raillé comme étant un simple jouet, derrière sa simplicité désarmante se cachent certaines fonctionnalités de langage très puissantes. De nombreuses applications JavaScript de premier plan sont apparues, ce qui montre qu'une connaissance approfondie de cette technologie est une compétence importante pour tout développeur Web.</p> <p>Il peut être utile de commencer avec un aperçu de l'histoire de ce langage. JavaScript a été créé en 1995 par Brendan Eich, un ingénieur de Netscape, et ce langage est sorti au grand jour pour la première fois avec Netscape 2 au début de l'année 1996. Il était au départ censé s'appeler LiveScript, mais a été renommé par une décision marketing néfaste dans le but de capitaliser sur la popularité du langage Java de Sun Microsystems, malgré le fait qu'ils n'aient que très peu en commun. Cela n'a jamais cessé d'être une source de confusion.</p> -<p>Quelques mois plus tard, Microsoft a lancé avec Internet Explorer 3 une version du langage globalement compatible, appelée JScript. Quelques mois après, Netscape a soumis le langage à l'<a class="external" href="https://www.ecma-international.org/">Ecma International</a>, une organisation de normalisation européenne, ce qui a permis d'aboutir à la première édition du standard <a href="/fr/ECMAScript">ECMAScript</a> en 1997. Ce standard a reçu une mise à jour importante appelée <a class="external" href="https://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript edition 3</a> en 1999, et est resté relativement stable depuis. La quatrième édition a été abandonnée suite à des différends portants sur la complexité du langage. De nombreuses sections de la quatrième édition ont été utilisées pour servir de fondation à la cinquième édition d'ECMAScript, publiée en décembre 2009. La sixième édition, qui apporte des nouveautés majeures a été publiée en juin 2015.</p> +<p>Quelques mois plus tard, Microsoft a lancé avec Internet Explorer 3 une version du langage globalement compatible, appelée JScript. Quelques mois après, Netscape a soumis le langage à l'<a href="https://www.ecma-international.org/">Ecma International</a>, une organisation de normalisation européenne, ce qui a permis d'aboutir à la première édition du standard <a href="/fr/docs/Glossary/ECMAScript">ECMAScript</a> en 1997. Ce standard a reçu une mise à jour importante appelée <a href="https://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript edition 3</a> en 1999, et est resté relativement stable depuis. La quatrième édition a été abandonnée suite à des différends portants sur la complexité du langage. De nombreuses sections de la quatrième édition ont été utilisées pour servir de fondation à la cinquième édition d'ECMAScript, publiée en décembre 2009. La sixième édition, qui apporte des nouveautés majeures a été publiée en juin 2015.</p> -<div class="note"> -<p><strong>Note :</strong> Dans la suite de cet article et à des fins de simplicité, nous utiliserons les termes « JavaScript » et « ECMAScript » pour désigner la même chose.</p> +<div class="notecard note"> + <p><b>Note :</b></p> + <p>Dans la suite de cet article et à des fins de simplicité, nous utiliserons les termes « JavaScript » et « ECMAScript » pour désigner la même chose.</p> </div> -<p>Cette stabilité est une excellente nouvelle pour les développeurs, parce qu'elle a donné aux différentes implémentations tout le temps nécessaire pour s'y adapter.</p> - <p>Contrairement à la plupart des langages de programmation, JavaScript n'a pas de concept d'entrée ou de sortie. Il est conçu pour s'exécuter comme un langage de script dans un environnement hôte, et c'est à cet environnement de fournir des mécanismes de communication avec le monde extérieur. L'environnement hôte le plus commun est un navigateur, mais des interpréteurs JavaScript existent également dans Adobe Acrobat, Photoshop, les images SVG, le moteur de widgets de Yahoo!, et même au sein d'environnements côté serveur tels que <a href="https://nodejs.org/">Node.js</a>. Cette liste ne se limite pas qu'à ces éléments et on retrouve également JavaScript dans les bases de données NoSQL telles que <a href="https://couchdb.apache.org/">Apache CouchDB</a>, les ordinateurs embarqués ou encore des environnements de bureaux comme <a href="https://www.gnome.org/">GNOME</a> (l'une des interfaces graphiques les plus populaires des systèmes d'exploitation GNU/Linux).</p> -<h2 id="Aperçu">Aperçu</h2> +<h2 id="Overview">Aperçu</h2> -<p>JavaScript est un langage dynamique multi-paradigme : il dispose de différents types, opérateurs, objets natifs et méthodes. Sa syntaxe s'inspire des langages Java et C, donc de nombreuses structures de ces langages s'appliquent également à JavaScript. À la différence de ces langages, JavaScript n'a pas de classes. Au lieu de cela, la fonctionnalité des classes est reprise par les prototypes d'objet (voir notamment <a href="/fr/docs/Web/JavaScript/Héritage_et_chaîne_de_prototypes">l'héritage et la chaîne de prototypes</a> ainsi que le sucre syntaxique pour les {{jsxref("Classes")}} apparu avec ES6/ES2015). L'autre grande différence tient dans le fait que les fonctions sont des objets, on peut donc stocker ces fonctions dans des variables et les transmettre comme n'importe quel objet.</p> +<p>JavaScript est un langage dynamique multi-paradigme : il dispose de différents types, opérateurs, objets natifs et méthodes. Sa syntaxe s'inspire des langages Java et C, donc de nombreuses structures de ces langages s'appliquent également à JavaScript. À la différence de ces langages, JavaScript n'a pas de classes. Au lieu de cela, la fonctionnalité des classes est reprise par les prototypes d'objet (voir notamment <a href="/fr/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">l'héritage et la chaîne de prototypes</a> ainsi que le sucre syntaxique pour les <a href="/fr/docs/Web/JavaScript/Reference/Classes"><code>Classes</code></a> apparues avec ES6/ES2015). L'autre grande différence tient dans le fait que les fonctions sont des objets, on peut donc stocker ces fonctions dans des variables et les transmettre comme n'importe quel objet.</p> -<p>Commençons par nous intéresser à la brique de base de tout langage : les types. Les programmes en JavaScript manipulent des valeurs, et ces valeurs appartiennent toutes à un type. Les types JavaScript sont :</p> +<p>Commençons par nous intéresser à la brique de base de tout langage : les types. Les programmes en JavaScript manipulent des valeurs, et ces valeurs appartiennent toutes à un type. Les types JavaScript sont :</p> <ul> - <li>Les nombres : {{jsxref("Number")}}</li> - <li>Les chaînes de caractères : {{jsxref("String")}}</li> - <li>Les booléens : {{jsxref("Boolean")}}</li> - <li>Les fonctions : {{jsxref("Function")}}</li> - <li>Les objets : {{jsxref("Object")}}</li> - <li>Les symboles : {{jsxref("Symbol")}} (apparus avec la sixième édition d'ECMAScript, ES2015)</li> + <li>Les nombres : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number"><code>Number</code></a></li> + <li>Les chaînes de caractères : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String"><code>String</code></a></li> + <li>Les booléens : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><code>Boolean</code></a></li> + <li>Les fonctions : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function"><code>Function</code></a></li> + <li>Les objets : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object"><code>Object</code></a></li> + <li>Les symboles : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Symbol"><code>Symbol</code></a> (apparus avec la sixième édition d'ECMAScript, ES2015)</li> </ul> -<p>On aura également {{jsxref("undefined")}} et {{jsxref("null")}}, qui sont relativement étranges. Les {{jsxref("Array","tableaux","",1)}} ou <em>Array</em> permettent d'organiser des séries d'objets au sein d'un même objet. Les {{jsxref("Date","dates","",1)}} et les {{jsxref("RegExp","expressions rationnelles","",1)}} ou <em>RegExp</em> qui sont également des objets immédiatement disponibles en JavaScript. Afin d'être cohérent, les fonctions sont aussi une sorte particulière d'objets, de sorte que le diagramme de types ressemble en fait plus à ceci :</p> +<p>On aura également <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/undefined"><code>undefined</code></a> et <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>, qui sont relativement étranges. Les <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array">tableaux</a> ou <em>Array</em> permettent d'organiser des séries d'objets au sein d'un même objet. Les <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date">dates</a> et les <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/RegExp">expressions régulières</a> ou <em>RegExp</em> qui sont également des objets immédiatement disponibles en JavaScript. Afin d'être cohérent, les fonctions sont aussi une sorte particulière d'objets, de sorte que le diagramme de types ressemble en fait plus à ceci :</p> <ul> - <li>{{jsxref("Number")}}</li> - <li>{{jsxref("String")}}</li> - <li>{{jsxref("Boolean")}}</li> - <li>{{jsxref("Symbol")}} (apparu avec la sixième édition d'ECMAScript, ES2015)</li> - <li>{{jsxref("Object")}} - <ul> - <li>{{jsxref("Function")}}</li> - <li>{{jsxref("Array")}}</li> - <li>{{jsxref("Date")}}</li> - <li>{{jsxref("RegExp")}}</li> - </ul> - </li> - <li>{{jsxref("null")}}</li> - <li>{{jsxref("undefined")}}</li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number"><code>Number</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String"><code>String</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><code>Boolean</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Symbol"><code>Symbol</code></a> (apparu avec la sixième édition d'ECMAScript, ES2015)</li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object"><code>Object</code></a> + <ul> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function"><code>Function</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date"><code>Date</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/RegExp"><code>RegExp</code></a></li> + </ul> + </li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a></li> + <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/undefined"><code>undefined</code></a></li> </ul> -<p>Enfin, il y a également quelques types natifs pour gérer les exceptions : {{jsxref("Error")}}.</p> +<p>Enfin, il y a également quelques types natifs pour gérer les exceptions : <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Error"><code>Error</code></a>.</p> -<h2 id="Les_nombres">Les nombres</h2> +<h2 id="numbers">Les nombres</h2> -<p>Les nombres en JavaScript sont « des valeurs au format IEEE 754 en double précision 64 bits », d'après la spécification. Les conséquences de ce choix sont intéressantes. Il n'y a par exemple pas de type entier en JavaScript, donc il vous faudra faire preuve d'un petit peu de prudence avec les opérations arithmétiques si vous avez l'habitude de faire des maths en C ou en Java. Attendez-vous à obtenir des résultats comme :</p> +<p>ECMAScript possède deux types numériques intégrés : <strong>Number</strong> et <strong>BigInt</strong>.</p> -<pre class="eval notranslate">0.1 + 0.2 == 0.30000000000000004 -</pre> +<p>Les nombres en JavaScript sont « des valeurs <a href="https://en.wikipedia.org/wiki/Double_precision_floating-point_format">au format IEEE 754 en double précision 64 bits</a> », d'après la spécification. Les conséquences de ce choix sont intéressantes. Il n'y a par exemple pas de type entier en JavaScript, donc il vous faudra faire preuve d'un petit peu de prudence avec les opérations arithmétiques si vous avez l'habitude de faire des maths en C ou en Java. Attendez-vous à obtenir des résultats comme :</p> -<p>Dans la pratique, les valeurs entières sont traîtées comme des entiers représentés sur 32 bits (certaines implémentations stockent également les entiers sur 32 bits). Cela est important quand on souhaite effectuer des opérations en binaire. Pour plus de détails, voir les articles sur <a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_binaires">les opérateurs binaires</a>.</p> +<pre class="brush: js">console.log(3 / 2); // 1.5, <em>pas</em> 1 +console.log(Math.floor(3 / 2)); // 1</pre> -<p>Les <a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_arithmétiques">opérateurs numériques</a> standards sont gérés, dont l'addition, la soustraction, le modulo (ou reste) arithmétique et ainsi de suite. Il y a également un objet natif, qui n'a pas été mentionné jusqu'à présent, appelé {{jsxref("Math")}}, qui permet de gérer certaines fonctions et constantes mathématiques plus avancées :</p> +<p>Ainsi, un <em>entier apparent</em> est en fait <em>implicitement un nombre à virgule flottante</em>.</p> -<pre class="brush: js notranslate">Math.sin(3.5); -var aire = Math.PI * r * r; -</pre> +<p>Aussi, faites attention à des choses comme :</p> -<p>On peut convertir une chaîne de caractères en un nombre entier à l'aide de la fonction intégrée {{jsxref("Objets_globaux/parseInt","parseInt()")}}. Elle reçoit la base de conversion comme second paramètre , qui devrait toujours être fourni afin de lever une éventuelle ambiguïté :</p> +<pre class="brush: js">0.1 + 0.2 == 0.30000000000000004;</pre> -<pre class="brush: js notranslate">parseInt("123", 10); // 123 -parseInt("010", 10); //10 -</pre> +<p>Dans la pratique, les valeurs entières sont traitées comme des entiers représentés sur 32 bits (certaines implémentations stockent également les entiers sur 32 bits). Cela est important quand on souhaite effectuer des opérations en binaire.</p> -<p>Si la base n'est pas indiquée, les résultats peuvent être surprenants dans les anciens navigateurs (avant 2013) :</p> +<p>Les <a href="/fr/docs/Web/JavaScript/Reference/Operators#arithmetic_operators">opérateurs arithmétiques</a> standards sont gérés, dont l'addition, la soustraction, le modulo (ou reste) arithmétique et ainsi de suite. Il y a également un objet natif, qui n'a pas été mentionné jusqu'à présent, appelé <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math"><code>Math</code></a>, qui permet de gérer certaines fonctions et constantes mathématiques plus avancées :</p> -<pre class="brush: js notranslate">parseInt("010"); // 8 -parseInt("0x10"); // 16 -</pre> +<pre class="brush: js">Math.sin(3.5); +var circonference = 2 * Math.PI * r;</pre> -<p>Cela se produit parce que la fonction {{jsxref("Objets_globaux/parseInt","parseInt()")}} a été implémentée pour traiter la chaîne comme un nombre octal à cause du zéro initial.</p> +<p>On peut convertir une chaîne de caractères en un nombre entier à l'aide de la fonction intégrée <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/parseInt"><code>parseInt()</code></a>. Elle reçoit la base de conversion comme second paramètre , qui devrait toujours être fourni afin de lever une éventuelle ambiguïté :</p> -<p>Si on souhaite convertir un nombre binaire en un entier, il suffit simplement de changer la base :</p> +<pre class="brush: js">parseInt("123", 10); // 123 +parseInt("010", 10); //10</pre> -<pre class="brush: js notranslate">parseInt("11", 2); // 3 -</pre> +<p>Si la base n'est pas indiquée, les résultats peuvent être surprenants dans les anciens navigateurs depuis 2013 environ. À moins que vous ne soyez certain du format de votre chaîne de caractères, vous pouvez obtenir des résultats surprenants sur ces anciens navigateurs :</p> + +<pre class="brush: js">parseInt("010"); // 8 +parseInt("0x10"); // 16</pre> + +<p>Cela se produit parce que la fonction <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/parseInt"><code>parseInt()</code></a> a été implémentée pour traiter la chaîne comme un nombre octal à cause du zéro initial.</p> + +<p>Si on souhaite convertir un nombre binaire en un entier, il suffit de changer la base :</p> -<p>De la même manière, vous pouvez traiter les nombres à virgule flottante à l'aide de la fonction intégrée {{jsxref("Objets_globaux/parseFloat","parseFloat()")}}, qui, à la différence de {{jsxref("Objets_globaux/parseInt","parseInt()")}}, utilise toujours la base 10.</p> +<pre class="brush: js">parseInt("11", 2); // 3</pre> -<p>On peut également utiliser l'opérateur unaire <code>+</code> pour convertir des valeurs en nombres :</p> +<p>De la même manière, vous pouvez traiter les nombres à virgule flottante à l'aide de la fonction intégrée <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/parseFloat"><code>parseFloat()</code></a>, qui, à la différence de <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/parseInt"><code>parseInt()</code></a>, utilise toujours la base 10.</p> -<pre class="brush: js notranslate">+ "42"; // 42 +<p>On peut également utiliser l'opérateur unaire <code>+</code> pour convertir des valeurs en nombres :</p> + +<pre class="brush: js">+ "42"; // 42 + "010"; // 10 -+ "0x10"; // 16 -</pre> ++ "0x10"; // 16</pre> -<p>Une valeur spéciale appelée {{jsxref("NaN")}} (qui signifie « <em>Not a Number</em> », soit « pas un nombre ») est renvoyée si la chaîne est non numérique :</p> +<p>Une valeur spéciale appelée <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/NaN"><code>NaN</code></a> (qui signifie « <em>Not a Number</em> », soit « pas un nombre ») est renvoyée si la chaîne est non numérique :</p> -<pre class="brush: js notranslate">parseInt("coucou", 10); // NaN -</pre> +<pre class="brush: js">parseInt("coucou", 10); // NaN</pre> -<p><code>NaN</code> est « toxique » : si cette valeur est fournie en entrée pour n'importe quelle opération mathématique, le résultat sera également <code>NaN</code> :</p> +<p><code>NaN</code> est « toxique » : si cette valeur est fournie en entrée pour n'importe quelle opération mathématique, le résultat sera également <code>NaN</code> :</p> -<pre class="brush: js notranslate">NaN + 5; // NaN -</pre> +<pre class="brush: js">NaN + 5; // NaN</pre> -<p>Cette valeur peut être détectée grâce à la fonction native {{jsxref("Objets_globaux/isNaN","isNaN()")}} :</p> +<p>Cette valeur peut être détectée grâce à la fonction native <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/isNaN"><code>isNaN()</code></a> :</p> -<pre class="brush: js notranslate">isNaN(NaN); // true -</pre> +<pre class="brush: js">Number.isNaN(NaN); // true +Number.isNaN('bonjour'); // false +Number.isNaN('1'); // false +Number.isNaN(undefined); // false +Number.isNaN({}); // false +Number.isNaN([1]) // false +Number.isNaN([1,2]) // false</pre> -<p>JavaScript dispose également de valeur spéciales pour l'infini {{jsxref("Infinity")}} et l'infini négatif (<code>-Infinity</code>) :</p> +<p>Mais ne testez pas le <code>NaN</code> en utilisant la fonction globale <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/isNaN"><code>isNaN()</code></a>, <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/isNaN#confusing_special-case_behavior">qui a un comportement peu intuitif</a> :</p> -<pre class="brush: js notranslate">1 / 0; // Infinity --1 / 0; // -Infinity +<pre class="brush: js">isNaN('bonjour'); // true +isNaN('1'); // false +isNaN(undefined); // true +isNaN({}); // true +isNaN([1]) // false +isNaN([1,2]) // true </pre> -<p>Il est possible de tester les valeurs <code>Infinity</code>, <code>-Infinity</code> et <code>NaN</code> à l'aide de la fonction native {{jsxref("Objets_globaux/isFinite","isFinite()")}} :</p> +<p>JavaScript dispose également de valeur spéciales pour l'infini <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Infinity"><code>Infinity</code></a> et l'infini négatif (<code>-Infinity</code>) :</p> -<pre class="brush: js notranslate">isFinite(1/0); // false +<pre class="brush: js">1 / 0; // Infinity +-1 / 0; // -Infinity</pre> + +<p>Il est possible de tester les valeurs <code>Infinity</code>, <code>-Infinity</code> et <code>NaN</code> à l'aide de la fonction native <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/isFinite"><code>isFinite()</code></a> :</p> + +<pre class="brush: js">isFinite(1/0); // false isFinite(-Infinity); // false -isFinite(NaN); // false -</pre> +isFinite(NaN); // false</pre> -<div class="note"><strong>Note :</strong> Les fonctions {{jsxref("Objets_globaux/parseFloat","parseFloat()")}} et {{jsxref("Objets_globaux/parseInt","parseInt()")}} traitent une chaîne de caractères jusqu'à ce qu'elles atteignent un caractère qui n'est pas valide pour le format numérique indiqué, puis renvoient le nombre traité jusqu'à ce point. Cependant, l'opérateur "+" convertit simplement la chaîne à <code>NaN</code> à partir du moment où la chaîne contient le moindre caractère non valide. Vous pouvez tester ce comportement en manipulant la chaîne "10.2abc" avec chaque méthode dans la console afin de mieux comprendre les différences.</div> +<div class="notecard note"> + <p><b>Note :</b></p> + <p>Les fonctions <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/parseFloat"><code>parseFloat()</code></a> et <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/parseInt"><code>parseInt()</code></a> traitent une chaîne de caractères jusqu'à ce qu'elles atteignent un caractère qui n'est pas valide pour le format numérique indiqué, puis renvoient le nombre traité jusqu'à ce point. Cependant, l'opérateur "+" convertit simplement la chaîne à <code>NaN</code> à partir du moment où la chaîne contient le moindre caractère non valide. Vous pouvez tester ce comportement en manipulant la chaîne "10.2abc" avec chaque méthode dans la console afin de mieux comprendre les différences.</p> +</div> -<h2 id="Les_chaînes_de_caractères">Les chaînes de caractères</h2> +<h2 id="strings">Les chaînes de caractères</h2> -<p>Les chaînes en JavaScript sont des séquences de caractères. Pour être plus précis, ce sont des séquences de <a href="/fr/docs/Web/JavaScript/Guide/Valeurs,_variables,_et_littéraux#Unicode">caractères Unicode</a>, chaque caractère étant représenté par un nombre de 16 bits. Cette nouvelle devrait être bien accueillie par toute personne qui a déjà eu affaire à des problèmes d'internationalisation.</p> +<p>Les chaînes en JavaScript sont des séquences de caractères. Pour être plus précis, ce sont des séquences de <a href="/fr/docs/Web/JavaScript/Guide/Grammar_and_types#unicode">caractères Unicode</a>, chaque caractère étant représenté par un nombre de 16 bits. Cette nouvelle devrait être bien accueillie par toute personne qui a déjà eu affaire à des problèmes d'internationalisation.</p> <p>Si vous voulez représenter un seul caractère, il suffit d'utiliser une chaîne qui contient un seul caractère.</p> -<p>Pour connaître la longueur d'une chaîne, utilisez sa propriété {{jsxref("String/length","length")}} :</p> +<p>Pour connaître la longueur d'une chaîne, utilisez sa propriété <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/length"><code>length</code></a> :</p> -<pre class="brush: js notranslate">"bonjour".length; // 7 -</pre> +<pre class="brush: js">"bonjour".length; // 7</pre> -<p>C'est notre première rencontre avec les objets JavaScript ! Les chaînes peuvent également être utilisées comme des objets. Elles possèdent aussi des <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/String#M.C3.A9thodes">méthodes</a> permettant de manipuler la chaîne et d'accéder à certaines informations sur cette chaîne de caractères :</p> +<p>C'est notre première rencontre avec les objets JavaScript ! Les chaînes peuvent également être utilisées comme des objets. Elles possèdent aussi des <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String#methods">méthodes</a> permettant de manipuler la chaîne et d'accéder à certaines informations sur cette chaîne de caractères :</p> -<pre class="brush: js notranslate">"bonjour".charAt(0); // "b" +<pre class="brush: js">"bonjour".charAt(0); // "b" "coucou monde".replace("coucou", "bonjour"); // "bonjour monde" -"bonjour".toUpperCase(); // "BONJOUR" -</pre> +"bonjour".toUpperCase(); // "BONJOUR"</pre> -<h2 id="Les_autres_types">Les autres types</h2> +<h2 id="other_types">Les autres types</h2> -<p>JavaScript fait la distinction entre {{jsxref("null")}}, qui est un objet de type <code>object</code> indiquant une absence délibérée de valeur, et {{jsxref("undefined")}} qui est un objet de type <code>undefined</code> indiquant une variable non initialisée — c'est-à-dire qui n'a pas encore été assignée. Nous parlerons des variables plus tard, mais en JavaScript il est possible de déclarer une variable sans lui assigner de valeur. Si vous faites cela, le type de la variable sera <code>undefined</code> qui est une constante.</p> +<p>JavaScript fait la distinction entre <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>, qui est un objet de type <code>object</code> indiquant une absence délibérée de valeur, et <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/undefined"><code>undefined</code></a> qui est un objet de type <code>undefined</code> indiquant une variable non initialisée — c'est-à-dire qui n'a pas encore été assignée. Nous parlerons des variables plus tard, mais en JavaScript il est possible de déclarer une variable sans lui assigner de valeur. Si vous faites cela, le type de la variable sera <code>undefined</code> qui est une constante.</p> -<p>JavaScript dispose d'un type booléen, dont les valeurs possibles sont <code>true</code> (vrai) et <code>false</code> (faux). L'un et l'autre sont des mots clés. Toute valeur peut être convertie en une valeur booléenne selon les règles suivantes :</p> +<p>JavaScript dispose d'un type booléen, dont les valeurs possibles sont <code>true</code> (vrai) et <code>false</code> (faux). L'un et l'autre sont des mots clés. Toute valeur peut être convertie en une valeur booléenne selon les règles suivantes :</p> <ol> - <li><code>false</code>, <code>0</code>, la chaîne vide (<code>""</code>), <code>NaN</code>, <code>null</code> et <code>undefined</code> deviennent toutes <code>false</code> </li> - <li>toutes les autres valeurs deviennent <code>true</code>.</li> + <li><code>false</code>, <code>0</code>, la chaîne vide (<code>""</code>), <code>NaN</code>, <code>null</code> et <code>undefined</code> deviennent toutes <code>false</code> </li> + <li>toutes les autres valeurs deviennent <code>true</code>.</li> </ol> -<p>Cette conversion peut être faite de manière explicite à l'aide de la fonction <code>Boolean()</code> :</p> +<p>Cette conversion peut être faite de manière explicite à l'aide de la fonction <code>Boolean()</code> :</p> -<pre class="brush: js notranslate">Boolean(""); // false -Boolean(234); // true -</pre> +<pre class="brush: js">Boolean(""); // false +Boolean(234); // true</pre> -<p>Cependant, c'est rarement nécessaire, puisque JavaScript effectuera cette conversion silencieusement chaque fois qu'il attend une valeur booléenne, comme par exemple dans une instruction <code>if</code> (voir plus bas). Pour cette raison, on parle souvent simplement de valeurs « vraies » et « fausses » pour indiquer des valeurs devenant respectivement <code>true</code> et <code>false</code> lorsqu'elles sont converties en valeurs booléennes.</p> +<p>Cependant, c'est rarement nécessaire, puisque JavaScript effectuera cette conversion silencieusement chaque fois qu'il attend une valeur booléenne, par exemple dans une instruction <code>if</code> (voir plus bas). Pour cette raison, on parle souvent simplement de valeurs « vraies » et « fausses » pour indiquer des valeurs devenant respectivement <code>true</code> et <code>false</code> lorsqu'elles sont converties en valeurs booléennes.</p> <p>Les opérations booléennes comme <code>&&</code> (<em>et</em> logique), <code>||</code> (<em>ou</em> logique) et <code>!</code> (<em>non</em> logique) sont également gérées, comme on le verra plus bas.</p> -<h2 id="Les_variables">Les variables</h2> +<h2 id="variables">Les variables</h2> -<p>En JavaScript, on peut déclarer de nouvelles variables grâce à l'un de ces trois mots-clés : <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/let">let</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/const">const</a></code>, ou <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/var" title="/en/JavaScript/Reference/Statements/var">var</a></code>.</p> +<p>En JavaScript, on peut déclarer de nouvelles variables grâce à l'un de ces trois mots-clés : <a href="/fr/docs/Web/JavaScript/Reference/Statements/let"><code>let</code></a>, <a href="/fr/docs/Web/JavaScript/Reference/Statements/const"><code>const</code></a>, ou <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/var" title="/en/JavaScript/Reference/Statements/var">var</a></code>.</p> <p><code>let</code> permet de déclarer des variables qui pourront être utilisées dans un bloc. La variable déclarée avec <code>let</code> est uniquement disponible dans le bloc qui contient la déclaration.</p> -<pre class="brush: js notranslate">let a; -let nom = "Simon"; -</pre> +<pre class="brush: js">let a; +let nom = "Simon";</pre> <p>Voici un exemple de <em>portée</em> avec <code>let</code> :</p> -<pre class="brush: js notranslate">// variableLet n'est pas utilisable ici +<pre class="brush: js">// variableLet n'est pas utilisable ici for ( let variableLet = 0; variableLet < 5; variableLet++ ) { // variableLet peut être utilisée ici } -// variableLet n'est pas utilisable ici -</pre> +// variableLet n'est pas utilisable ici</pre> <p><code>const</code> permet de déclarer des variables dont la valeur ne doit pas changer. Une variable déclarée avec <code>const</code> est disponible dans le bloc dans lequel elle est déclarée.</p> -<pre class="brush: js notranslate">// On définit la constante Pi -const Pi = 3.14; - -// L'instruction qui suit provoquera une -// erreur car on veut affecter une nouvelle -// valeur à une constante. -Pi = 1; +<pre class="brush: js"> +const Pi = 3.14; // la constante Pi est définie +Pi = 1; // produira une erreur, car vous ne pouvez pas modifier une variable constante. </pre> <p><code>var</code> est le mot-clé le plus fréquemment utilisé pour déclarer des variables. Ce mot-clé était disponible avant <code>let</code> et <code>const</code> (c'était alors le seul qui permettait de déclarer des variables). Une variable qu'on déclare avec <code>var</code> est disponible dans le bloc de la fonction dans laquelle elle est déclarée.</p> -<pre class="brush: js notranslate">var a; +<pre class="brush: js">var a; var nom = "simon";</pre> <p>Voici un exemple pour étudier la portée d'une variable déclarée avec <code>var</code> :</p> -<pre class="brush: js notranslate">// variableVar *est* utilisable ici +<pre class="brush: js">// variableVar *est* utilisable ici -for (var variableVar = 0; variableVar < 5; variableVar++) { +for (let variableVar = 0; variableVar < 5; variableVar++) { // variableVar *est* également disponible ici } -// variableVar *est* toujours disponible ici -</pre> +// variableVar *est* toujours disponible ici</pre> <p>Si on déclare une variable sans lui affecter aucune valeur, son type sera alors <code>undefined</code>.</p> -<p>JavaScript possède une différence importante quant aux autres langages de programmation comme Java : en JavaScript, les blocs ne créent pas de portées pour les variables déclarées avec <code>var</code>, c'est la fonction qui gère la portée d'une variable déclarée avec <code>var</code>. Avec ECMAScript 2015, les instructions de déclarations, <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/let">let</a></code> et <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/const">const</a></code> permettent de créer des variables dont la portée est limitée à celle du bloc qui l'englobe.</p> +<p>JavaScript possède une différence importante quant aux autres langages de programmation comme Java : en JavaScript, les blocs ne créent pas de portées pour les variables déclarées avec <code>var</code>, c'est la fonction qui gère la portée d'une variable déclarée avec <code>var</code>. Avec ECMAScript 2015, les instructions de déclarations, <a href="/fr/docs/Web/JavaScript/Reference/Statements/let"><code>let</code></a> et <a href="/fr/docs/Web/JavaScript/Reference/Statements/const"><code>const</code></a> permettent de créer des variables dont la portée est limitée à celle du bloc qui l'englobe.</p> -<h2 id="Les_opérateurs">Les opérateurs</h2> +<h2 id="operators">Les opérateurs</h2> -<p>Les opérateurs numériques en JavaScript sont <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> et <code>%</code> (qui est <a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_arithmétiques#Reste_()">l'opérateur de reste, à ne pas confondre avec le « modulo » mathématique</a>). Les valeurs sont affectées à l'aide de <code>=</code> et il existe également des opérateurs d'affectation combinés comme <code>+=</code> et <code>-=</code>. Ils sont équivalents à <code>x = x <em>opérateur</em> y</code>.</p> +<p>Les opérateurs numériques en JavaScript sont <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> et <code>%</code> (qui est <a href="/fr/docs/conflicting/Web/JavaScript/Reference/Operators#remainder_()">l'opérateur de reste, à ne pas confondre avec le « modulo » mathématique</a>). Les valeurs sont affectées à l'aide de <code>=</code> et il existe également des opérateurs d'affectation combinés comme <code>+=</code> et <code>-=</code>. Ils sont équivalents à <code>x = x <em>opérateur</em> y</code>.</p> -<pre class="brush: js notranslate">x += 5; -x = x + 5; -</pre> +<pre class="brush: js">x += 5; +x = x + 5;</pre> <p>Vous pouvez utiliser <code>++</code> et <code>--</code> respectivement pour incrémenter et pour décrémenter. Ils peuvent être utilisés comme opérateurs préfixes ou suffixes.</p> -<p>L'<a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_arithmétiques#Addition_(.2B)">opérateur <code>+</code> </a> se permet également de concaténer des chaînes :</p> +<p>L'<a href="/fr/docs/conflicting/Web/JavaScript/Reference/Operators#addition_(.2b)">opérateur <code>+</code> </a> se permet également de concaténer des chaînes :</p> -<pre class="brush: js notranslate">"coucou" + " monde" // "coucou monde" -</pre> +<pre class="brush: js">"coucou" + " monde"; // "coucou monde"</pre> -<p>Si vous additionnez une chaîne à un nombre (ou une autre valeur), tout est d'abord converti en une chaîne. Ceci pourrait vous surprendre :</p> +<p>Si vous additionnez une chaîne à un nombre (ou une autre valeur), tout est d'abord converti en une chaîne. Ceci pourrait vous surprendre :</p> -<pre class="brush: js notranslate">"3" + 4 + 5; // "345" -3 + 4 + "5"; // "75" -</pre> +<pre class="brush: js">"3" + 4 + 5; // "345" +3 + 4 + "5"; // "75"</pre> <p>L'ajout d'une chaîne vide à quelque chose est une manière utile de la convertir en une chaîne.</p> -<p>Les <a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_de_comparaison">comparaisons</a> en JavaScript se font à l'aide des opérateurs <code><</code>, <code>></code>, <code><=</code> et <code>>=</code>. Ceux-ci fonctionnent tant pour les chaînes que pour les nombres. L'égalité est un peu moins évidente. L'opérateur double égal effectue une équivalence si vous lui donnez des types différents, ce qui donne parfois des résultats intéressants :</p> +<p>Les <a href="/fr/docs/Web/JavaScript/Reference/Operators">comparaisons</a> en JavaScript se font à l'aide des opérateurs <code><</code>, <code>></code>, <code><=</code> et <code>>=</code>. Ceux-ci fonctionnent tant pour les chaînes que pour les nombres. L'égalité est un peu moins évidente. L'opérateur double égal effectue une équivalence si vous lui donnez des types différents, ce qui donne parfois des résultats intéressants :</p> -<pre class="brush: js notranslate">123 == "123"; // true -1 == true; // true -</pre> +<pre class="brush: js">123 == "123"; // true +1 == true; // true</pre> -<p>Pour éviter les calculs d'équivalences de types, utilisez l'opérateur triple égal :</p> +<p>Pour éviter les calculs d'équivalences de types, utilisez l'opérateur triple égal :</p> -<pre class="brush: js notranslate">123 === "123"; //false -true === true; // true -</pre> +<pre class="brush: js">123 === "123"; //false +true === true; // true</pre> <p>Les opérateurs <code>!=</code> et <code>!==</code> existent également.</p> -<p>JavaScript dispose également d'<a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_binaires">opérations bit à bit</a>.</p> +<p>JavaScript dispose également d'<a href="/fr/docs/Web/JavaScript/Reference/Operators">opérations bit à bit</a>.</p> -<h2 id="Les_structures_de_contrôle">Les structures de contrôle</h2> +<h2 id="control_structures">Les structures de contrôle</h2> -<p>JavaScript dispose d'un ensemble de structures de contrôle similaires aux autres langages de la famille du langage C. Les structures conditionnelles sont présentes avec <code>if</code> et <code>else</code> ; lesquels peuvent être chaînés si nécessaire :</p> +<p>JavaScript dispose d'un ensemble de structures de contrôle similaires aux autres langages de la famille du langage C. Les structures conditionnelles sont présentes avec <code>if</code> et <code>else</code> ; lesquels peuvent être chaînés si nécessaire :</p> -<pre class="brush: js notranslate">var nom = "des chatons"; +<pre class="brush: js">let nom = "des chatons"; if (nom == "des chiots") { nom += " !"; } else if (nom == "des chatons") { @@ -277,63 +279,58 @@ if (nom == "des chiots") { } else { nom = " !" + nom; } -nom == "des chatons !!" -</pre> +nom == "des chatons !!"</pre> -<p>JavaScript dispose également de boucles <code>while</code> et <code>do-while</code>. Les premières permettent de former des boucles basiques ; les secondes permettent de construire des boucles qui seront exécutées au moins une fois :</p> +<p>JavaScript dispose également de boucles <code>while</code> et <code>do-while</code>. Les premières permettent de former des boucles basiques ; les secondes permettent de construire des boucles qui seront exécutées au moins une fois :</p> -<pre class="brush: js notranslate">while (true) { - // une boucle infinie ! +<pre class="brush: js">while (true) { + // une boucle infinie ! } +let input; do { - var input = getInput(); -} while (inputNonValide(input)) -</pre> + input = getInput(); +} while (inputNonValide(input));</pre> -<p>Les boucles <code>for</code> en JavaScript sont les mêmes qu'en C et en Java : elles permettent de fournir les informations de contrôle de la boucle en une seule ligne.</p> +<p>Les boucles <code>for</code> en JavaScript sont les mêmes qu'en C et en Java : elles permettent de fournir les informations de contrôle de la boucle en une seule ligne.</p> -<pre class="brush: js notranslate">for (var i = 0; i < 5; i++) { +<pre class="brush: js">for (let i = 0; i < 5; i++) { // Sera exécutée cinq fois -} -</pre> +}</pre> -<p>JavaScript permet également d'utiliser deux autres types de boucles : <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for...of">for...of</a></code> :</p> +<p>JavaScript permet également d'utiliser deux autres types de boucles : <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></code> :</p> -<pre class="brush: js notranslate">for (let value of array) { +<pre class="brush: js">for (let value of array) { // utiliser des instructions // pour manipuler la valeur value }</pre> -<p>et <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for...in">for...in</a></code> :</p> +<p>et <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/for...in">for...in</a></code> :</p> -<pre class="brush: js notranslate">for (let propriété in objet) { +<pre class="brush: js">for (let propriété in objet) { // utiliser des instructions // pour manipuler la propriété }</pre> -<p>Les opérateurs <code>&&</code> et <code>||</code> utilisent une logique de court-circuit, ce qui signifie qu'ils exécuteront leur second opérande ou non selon la valeur du premier. C'est très utile pour vérifier qu'un objet n'est pas égal à <code>null</code> avant d'essayer d'accéder à ses attributs :</p> +<p>Les opérateurs <code>&&</code> et <code>||</code> utilisent une logique de court-circuit, ce qui signifie qu'ils exécuteront leur second opérande ou non selon la valeur du premier. C'est très utile pour vérifier qu'un objet n'est pas égal à <code>null</code> avant d'essayer d'accéder à ses attributs :</p> -<pre class="brush: js notranslate">var nom = o && o.getNom(); -</pre> +<pre class="brush: js">let nom = o && o.getNom();</pre> -<p>Ou pour définir des valeurs par défaut :</p> +<p>Ou pour définir des valeurs par défaut :</p> -<pre class="brush: js notranslate">var nom = autreNom || "nomParDéfaut"; -</pre> +<pre class="brush: js">let nom = autreNom || "nomParDéfaut";</pre> <p>De la même façon, le OU peut être utilisé pour mettre en cache des valeurs :</p> -<pre class="brush: js notranslate">var nom = nomEnCache || (nomEnCache = getNom());</pre> +<pre class="brush: js">let nom = nomEnCache || (nomEnCache = getNom());</pre> -<p>JavaScript propose également un opérateur ternaire pour les assignations conditionnelles en une ligne :</p> +<p>JavaScript propose également un opérateur ternaire pour les assignations conditionnelles en une ligne :</p> -<pre class="brush: js notranslate">var permis = (age > 18) ? "oui" : "non"; -</pre> +<pre class="brush: js">let permis = (age > 18) ? "oui" : "non";</pre> -<p>L'instruction <code>switch</code> peut être utilisée pour différentes branches de code basées sur un nombre ou une chaîne :</p> +<p>L'instruction <code>switch</code> peut être utilisée pour différentes branches de code basées sur un nombre ou une chaîne :</p> -<pre class="brush: js notranslate">switch (action) { +<pre class="brush: js">switch (action) { case 'dessiner': dessine(); break; @@ -342,24 +339,22 @@ do { break; default: neRienFaire(); -} -</pre> +}</pre> -<p>Si vous n'ajoutez pas d'instruction <code>break</code>, l'exécution va se poursuivre au niveau suivant. C'est rarement ce qui est désiré, en fait ça vaut même la peine de préciser dans un commentaire si la poursuite au cas suivant est délibérée pour aider au débogage :</p> +<p>Si vous n'ajoutez pas d'instruction <code>break</code>, l'exécution va se poursuivre au niveau suivant. C'est rarement ce qui est désiré, en fait ça vaut même la peine de préciser dans un commentaire si la poursuite au cas suivant est délibérée pour aider au débogage :</p> -<pre class="brush: js notranslate">switch (a) { +<pre class="brush: js">switch (a) { case 1: // identique au cas 2 case 2: mange(); break; default: nerienfaire(); -} -</pre> +}</pre> -<p>La clause <code>default</code> est optionnelle. Vous pouvez placer des expressions à la fois dans la partie <code>switch</code> et dans les cas à gérer si vous voulez ; les comparaisons entre les deux se font comme si on avait utilisé l'opérateur <code>===</code> :</p> +<p>La clause <code>default</code> est optionnelle. Vous pouvez placer des expressions à la fois dans la partie <code>switch</code> et dans les cas à gérer si vous voulez ; les comparaisons entre les deux se font comme si on avait utilisé l'opérateur <code>===</code> :</p> -<pre class="brush: js notranslate" id="Les_objets">switch (1 + 3){ +<pre class="brush: js" id="Les_objets">switch (1 + 3){ case 2 + 2: yay(); break; @@ -367,248 +362,229 @@ do { nArriveJamais(); }</pre> -<h2 id="Les_objets_2">Les objets</h2> +<h2 id="objects">Les objets</h2> -<p>Les objets en JavaScript sont simplement des collections de paires nom-valeur. Dans ce sens, ils sont similaires aux :</p> +<p>Les objets en JavaScript sont simplement des collections de paires nom-valeur. Dans ce sens, ils sont similaires aux :</p> <ul> - <li>dictionnaires en Python,</li> - <li>hashs en Perl et Ruby,</li> - <li>tables de hashing en C et C++,</li> - <li>HashMaps en Java,</li> - <li>tableaux associatifs en PHP.</li> + <li>dictionnaires en Python,</li> + <li>hashs en Perl et Ruby,</li> + <li>tables de hashing en C et C++,</li> + <li>HashMaps en Java,</li> + <li>tableaux associatifs en PHP.</li> </ul> -<p>Le fait que cette structure de données soit si largement utilisée est un témoignage de sa polyvalence. Puisque tout (sauf les types de base) est un objet en JavaScript, tout programme écrit dans ce langage implique naturellement un grand nombre de recherches dans des tables de hashing. C'est une bonne chose que ce soit si rapide !</p> +<p>Le fait que cette structure de données soit si largement utilisée est un témoignage de sa polyvalence. Puisque tout (sauf les types de base) est un objet en JavaScript, tout programme écrit dans ce langage implique naturellement un grand nombre de recherches dans des tables de hashing. C'est une bonne chose que ce soit si rapide !</p> -<p>La partie « nom » est une chaîne JavaScript, tandis que la partie « valeur » peut être n'importe quelle valeur JavaScript, y compris d'autres objets. Cela permet de construire des structures de données de n'importe quel niveau de complexité.</p> +<p>La partie « nom » est une chaîne JavaScript, tandis que la partie « valeur » peut être n'importe quelle valeur JavaScript, y compris d'autres objets. Cela permet de construire des structures de données de n'importe quel niveau de complexité.</p> -<p>Il existe deux façons très simples pour créer un objet vide :</p> +<p>Il existe deux façons très simples pour créer un objet vide :</p> -<pre class="brush: js notranslate">var obj = new Object(); -</pre> +<pre class="brush: js">var obj = new Object();</pre> -<p>Et :</p> +<p>Et :</p> -<pre class="brush: js notranslate">var obj = {}; -</pre> +<pre class="brush: js">var obj = {};</pre> -<p>Ces deux lignes sont sémantiquement équivalentes ; la seconde est appelée la syntaxe littérale d'objet, et est beaucoup plus pratique. Cette syntaxe n'existait pas dans les toutes premières versions du langage, c'est pourquoi on voit parfois du code utilisant l'ancienne méthode. Cette seconde syntaxe se rapproche également du format JSON.</p> +<p>Ils sont sémantiquement équivalents ; la seconde écriture est appelée syntaxe littérale d'objet et est plus pratique. Cette syntaxe est également au cœur du format JSON et doit être privilégiée à tout moment.</p> -<p>Une fois l'objet créé, ses propriétés peuvent à nouveau être consultées de deux manières différentes :</p> +<p>Une fois l'objet créé, ses propriétés peuvent à nouveau être consultées de deux manières différentes :</p> -<pre class="brush: js notranslate">obj.nom = "Simon" -var nom = obj.nom; -</pre> +<pre class="brush: js">var obj = { + name: 'Carotte', + _for: 'Max', // Le mot "for" est un mot réservé, utilisez plutôt "_for". + details: { + color: 'orange', + size: 12 + } +};</pre> -<p>Et…</p> +<p>L'accès aux attributs peut être enchaîné :</p> -<pre class="brush: js notranslate">obj["nom"] = "Simon"; -var nom = obj["nom"]; -</pre> +<pre class="brush: js">obj.details.color; // orange +obj['details']['size']; // 12</pre> -<p>Ces lignes sont également sémantiquement équivalentes. La seconde méthode a l'avantage de fournir le nom de l'attribut de l'objet dans une chaîne, ce qui signifie qu'il peut être calculé au moment de l'exécution (mais ce qui peut empêcher certaines optimisations du moteur JavaScript). Elle peut également être utilisée pour définir et lire des propriétés dont les noms sont des <a href="/fr/docs/Web/JavaScript/Reference/Grammaire_lexicale#Mots-cl.C3.A9s">mots réservés</a> :</p> +<p>L'exemple suivant crée un prototype d'objet (<code>Person</code>) et une instance de ce prototype (<code>you</code>).</p> -<pre class="brush: js notranslate">obj.for = "Simon"; // avant ES5 erreur de syntaxe, "for" est un mot réservé -obj.for = "Simon"; // OK à partir d'ES5 -obj["for"] = "Simon"; // fonctionne très bien -</pre> +<pre class="brush: js">function Person(name, age) { + this.name = name; + this.age = age; +} -<div class="note"> -<p><strong>Note :</strong> ECMAScript 5 permet d'utiliser les mots-clés réservés pour des noms de propriétés, même si ceux-ci ne sont pas encadrés par des doubles quotes. Pour plus de précisions, voir <a href="https://es5.github.io/#x10.2.1.2">le texte de la spécification à ce sujet</a> (différence entre Identifier et IdentifierName). Cependant, pour des raisons de lisibilité, on préfèrera ne pas utiliser les mots-clés pour désigner des propriétés.</p> -</div> +// Définir un objet +var you = new Person('You', 24); +// Nous créons une nouvelle personne nommée "Vous" âgée de 24 ans.</pre> -<p>La syntaxe littérale d'objet peut être utilisée pour initialiser un objet dans son intégralité :</p> +<p><strong>Une fois créé</strong>, les propriétés d'un objet peuvent à nouveau être atteintes de l'une des deux manières suivantes :</p> -<pre class="brush: js notranslate">var obj = { - nom: "Carotte", - for: "Max", - details: { - couleur: "orange", - taille: 12 - } -}; -</pre> +<pre class="brush: js">// notation par points +obj.name = 'Simon'; +var name = obj.name;</pre> -<p>Les accès à des attributs peuvent aussi être chaînés :</p> +<p>Et...</p> -<pre class="brush: js notranslate">obj.details.couleur; // orange -obj["details"]["taille"]; // 12 -</pre> +<pre class="brush: js">// notation entre crochets +obj['name'] = 'Simon'; +var name = obj['name']; +// on peut utiliser une variable pour définir une clé +var user = prompt('what is your key?'); +obj[user] = prompt('what is its value?');</pre> + +<p>Ces lignes sont également sémantiquement équivalentes. La seconde méthode a l'avantage de fournir le nom de l'attribut de l'objet dans une chaîne, ce qui signifie qu'il peut être calculé au moment de l'exécution (mais ce qui peut empêcher certaines optimisations du moteur JavaScript). Elle peut également être utilisée pour définir et lire des propriétés dont les noms sont des <a href="/fr/docs/Web/JavaScript/Reference/Lexical_grammar#keywords">mots réservés</a> :</p> -<p>Pour plus d'informations sur les objets et les prototypes, on pourra consulter <code><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/prototype">Object.prototype</a></code> et l'article sur <a href="/fr/docs/Web/JavaScript/H%C3%A9ritage_et_cha%C3%AEne_de_prototypes">l'héritage et la chaîne de prototypes</a>.</p> +<pre class="brush: js">obj.for = "Simon"; // erreur de syntaxe, car "for" est un mot réservé +obj["for"] = "Simon"; // fonctionne très bien</pre> + +<div class="notecard note"> + <p><b>Note :</b></p> + <p>À partir de l'ECMAScript 5, les mots réservés peuvent être utilisés comme noms de propriétés d'objets "en vrac". Cela signifie qu'ils n'ont pas besoin d'être "habillés" de guillemets lors de la définition des littéraux d'objet. Voir <a href="https://es5.github.io/#x7.6.1"></a>la spécification de l'ES5</a>.</p> +</div> -<h2 id="Les_tableaux">Les tableaux</h2> +<p>Pour en savoir plus sur les objets et les prototypes, voir <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object.prototype</a>. Pour une explication des prototypes d'objets et des chaînes de prototypes, voir l'<a href="/fr/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">héritage et chaîne de prototype</a>.</p> + +<div class="notecard note"> + <p><b>Note :</b></p> + <p>À partir d'ECMAScript 2015, les clés des objets peuvent être définies par la variable en utilisant la notation entre parenthèses lors de sa création. <code>{[phoneType] : 12345}</code> est possible au lieu de simplement <code>var userPhone = {}; userPhone[phoneType] = 12345;</code>.</p> +</div> + +<h2 id="arrays">Les tableaux</h2> <p>Les tableaux (<em>Arrays</em>) en JavaScript sont en fait un type spécial d'objets. Ils fonctionnent d'une façon tout à fait similaire aux objets normaux (on peut naturellement accéder aux propriétés numériques avec la syntaxe des crochets <code>[]</code>), mais ils ont également une propriété magique appelée <code>length</code>. Elle vaut toujours un de plus que le plus grand indice dans le tableau.</p> -<p>L'ancienne manière de créer des tableaux est celle-ci :</p> +<p>L'ancienne manière de créer des tableaux est celle-ci :</p> -<pre class="brush: js notranslate">var a = new Array(); +<pre class="brush: js">var a = new Array(); a[0] = "chien"; a[1] = "chat"; a[2] = "poule"; -a.length; // 3 -</pre> +a.length; // 3</pre> -<p>Une notation plus pratique est la syntaxe littérale :</p> +<p>Une notation plus pratique est la syntaxe littérale :</p> -<pre class="brush: js notranslate">var a = ["chien", "chat", "poule"]; -a.length; // 3 -</pre> - -<div class="warning"> -<p>Laisser une virgule à la fin de la syntaxe littérale produit des résultats incohérents entre les différents navigateurs, bien qu'il soit spécifié que la dernière virgule doit être ignorée et que les éventuelles virgules précédentes définissent des éléments <code>undefined</code>. Il n'est pas recommandé de laisser des virgules en fin de notation littérale.</p> -</div> +<pre class="brush: js">var a = ["chien", "chat", "poule"]; +a.length; // 3</pre> -<p>Notez que <code>array.length</code> ne correspond pas nécessairement au nombre d'éléments dans le tableau. Observez le code suivant :</p> +<p>Notez que <code>array.length</code> ne correspond pas nécessairement au nombre d'éléments dans le tableau. Observez le code suivant :</p> -<pre class="brush: js notranslate">var a = ["chien", "chat", "poule"]; +<pre class="brush: js">var a = ["chien", "chat", "poule"]; a[100] = "renard"; -a.length // 101 -</pre> +a.length // 101</pre> -<p>Rappelez-vous : la longueur du tableau vaut simplement un de plus que l'indice le plus élevé.</p> +<p>Rappelez-vous : la longueur du tableau vaut simplement un de plus que l'indice le plus élevé.</p> -<p>Si vous interrogez un élément de tableau non existant, vous obtenez <code>undefined</code> :</p> +<p>Si vous interrogez un élément de tableau non existant, vous obtenez <code>undefined</code> :</p> -<pre class="brush: js notranslate">typeof(a[90]); // undefined -</pre> +<pre class="brush: js">typeof(a[90]); // undefined</pre> -<p>Si vous prenez cela en compte, il est possible de parcourir un tableau à l'aide de la boucle suivante :</p> +<p>Si vous prenez cela en compte, il est possible de parcourir un tableau à l'aide de la boucle suivante :</p> -<pre class="brush: js notranslate">for (var i = 0; i < a.length; i++) { +<pre class="brush: js">for (let i = 0; i < a.length; i++) { // Faire quelque chose avec a[i] -} -</pre> - -<p>Ce n'est pas la solution la plus performante, parce que l'on examine la propriété <code>length</code> à chaque tour de boucle. Une version améliorée est :</p> - -<pre class="brush: js notranslate">for (var i = 0, len = a.length; i < len; i++) { - // Faire quelque chose avec a[i] -} -</pre> - -<p>Mais il est possible d'exprimer cela encore mieux :</p> - -<pre class="brush: js notranslate">for (var i = 0, item; item = a[i]; i++) { - // Faire quelque chose avec item -} -</pre> - -<p>Ici on définit deux variables. La véracité de l'affectation dans la partie médiane de la boucle <code>for</code> est également vérifiée — si elle est vraie, la boucle continue. Étant donné que <code>i</code> est incrémentée à chaque fois, les éléments du tableau seront affectés à la variable <code>item</code> dans un ordre séquentiel. La boucle s'arrête lorsque la vérification d'un élément renvoie faux (comme c'est le cas d'une valeur <code>undefined</code>).</p> - -<p>Notez que cette astuce ne peut être utilisée que pour des tableaux qui ne comprennent pas d'autres valeurs qui pourraient renvoyer une valeur fausse (des tableaux d'objets ou de nœuds <a href="/fr/docs/Référence_du_DOM_Gecko">DOM</a> par exemple). Si vous parcourez des données numériques parmi lesquelles pourrait se trouver un zéro, des chaînes dont l'une pourrait être vide ou un tableau non continu, vous devrez utiliser la variante avec <code>i, len</code>.</p> - -<p>Une autre manière de parcourir un tableau est d'utiliser une boucle <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for...in">for...in</a></code>. Notez que si quelqu'un ajoutait d'autres propriétés à <code>Array.prototype</code>, elles seraient également parcourues par cette boucle et c'est pour cette raison que cette méthode est déconseillée :</p> - -<pre class="brush: js notranslate">for (var i in a) { - // faire quelque chose avec a[i] -} -</pre> +}</pre> -<p>En revanche avec la boucle <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for...of">for...of</a></code>, apparue avec ECMAScript 2015, on ne parcourt que les éléments du tableau (ou de tout autre itérable) :</p> +<p>ES2015 a introduit la boucle plus concise <a href="/fr/docs/Web/JavaScript/Reference/Statements/for...of"><code>for</code>...<code>of</code></a> pour les objets itérables tels que les tableaux :</p> -<pre class="brush: js notranslate">for (let elem of a){ - // faire quelque chose avec elem +<pre class="brush: js">for (const currentValue of a) { + // Faire quelque chose avec currentValue }</pre> -<p>Avec ECMAScript 5, on peut également parcourir un tableau avec la méthode <code>forEach()</code> :</p> +<p>Vous pourriez également itérer sur un tableau en utilisant une boucle <a href="/fr/docs/Web/JavaScript/Reference/Statements/for...in"><code>for</code>...<code>in</code></a>, cependant cela n'itère pas sur les éléments du tableau, mais sur les indices du tableau. De plus, si quelqu'un ajoutait de nouvelles propriétés à <code>Array.prototype</code>, elles seraient également itérées par une telle boucle. Par conséquent, ce type de boucle n'est pas recommandé pour les tableaux.</p> -<pre class="brush: js notranslate">["chien", "chat", "poule"].forEach(function(valeurCourante, index, array) { - // Faire quelque chose avec valeurCourante et array[index] -});</pre> +<p>Une autre façon d'itérer sur un tableau qui a été ajoutée avec ECMAScript 5 est <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach"><code>forEach()</code></a> :</p> -<p>Si vous désirez ajouter un élément à un tableau, la manière la plus sûre est de faire ceci :</p> - -<pre class="eval notranslate">a.push(element); -</pre> +<pre class="brush: js">['chien', 'chat', 'poule'].forEach(function(currentValue, index, array) { + // Faire quelque chose avec currentValue ou array[index] +});</pre> -<table> - <thead> - <tr> - <th scope="col">Nom de la méthode</th> - <th scope="col">Description</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>a.toString()</code></td> - <td>Renvoie une chaîne composée des différents éléments auxquels on a appliqué <code>toString()</code>, séparés par des virgules.</td> - </tr> - <tr> - <td><code>a.toLocaleString()</code></td> - <td>Renvoie une chaîne composée des différents éléments auxquels on a appliqué <code>toLocaleString()</code>, séparés par des virgules.</td> - </tr> - <tr> - <td><code>a.concat(item1[, item2[, ...[, itemN]]])</code></td> - <td>Renvoie un nouveau tableau auquel on a ajouté les éléments.</td> - </tr> - <tr> - <td><code>a.join(sep)</code></td> - <td>Convertit le tableau en une chaîne dont les valeurs sont séparées par le paramètre <code>sep</code>.</td> - </tr> - <tr> - <td><code>a.pop()</code></td> - <td>Renvoie le dernier élément du tableau et le retire du tableau.</td> - </tr> - <tr> - <td><code>a.push(item1, ..., itemN)</code></td> - <td>Ajoute un ou plusieurs éléments à la fin du tableau.</td> - </tr> - <tr> - <td><code>a.reverse()</code></td> - <td>Retourne le tableau.</td> - </tr> - <tr> - <td><code>a.shift()</code></td> - <td>Renvoie le premier élément du tableau et le retire du tableau.</td> - </tr> - <tr> - <td><code>a.slice(début[, fin])</code></td> - <td>Renvoie un sous-tableau.</td> - </tr> - <tr> - <td><code>a.sort([cmpfn])</code></td> - <td>Trie le tableau (avec une fonction de comparaison optionnelle).</td> - </tr> - <tr> - <td><code>a.splice(début, delcount[, item1[, ...[, itemN]]])</code></td> - <td>Permet de modifier un tableau en en supprimant une partie et en la remplaçant avec plus d'éléments.</td> - </tr> - <tr> - <td><code>a.unshift(item1[, item2[, ...[, itemN]]])</code></td> - <td>Ajoute des éléments au début du tableau.</td> - </tr> - </tbody> +<p>Si vous voulez ajouter un élément à un tableau, procédez comme suit :</p> + +<pre class="brush: js">a.push(item);</pre> + +<p>Les tableaux sont accompagnés d'un certain nombre de méthodes. Voir également la <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array">documentation complète sur les méthodes des tableaux</a>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Nom de la méthode</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>a.toString()</code></td> + <td>Renvoie une chaîne composée des différents éléments auxquels on a appliqué <code>toString()</code>, séparés par des virgules.</td> + </tr> + <tr> + <td><code>a.toLocaleString()</code></td> + <td>Renvoie une chaîne composée des différents éléments auxquels on a appliqué <code>toLocaleString()</code>, séparés par des virgules.</td> + </tr> + <tr> + <td><code>a.concat(item1[, item2[, ...[, itemN]]])</code></td> + <td>Renvoie un nouveau tableau auquel on a ajouté les éléments.</td> + </tr> + <tr> + <td><code>a.join(sep)</code></td> + <td>Convertit le tableau en une chaîne dont les valeurs sont séparées par le paramètre <code>sep</code>.</td> + </tr> + <tr> + <td><code>a.pop()</code></td> + <td>Renvoie le dernier élément du tableau et le retire du tableau.</td> + </tr> + <tr> + <td><code>a.push(item1, ..., itemN)</code></td> + <td>Ajoute un ou plusieurs éléments à la fin du tableau.</td> + </tr> + <tr> + <td><code>a.shift()</code></td> + <td>Renvoie le premier élément du tableau et le retire du tableau.</td> + </tr> + <tr> + <td><code>a.unshift(item1[, item2[, ...[, itemN]]])</code></td> + <td>Ajoute des éléments au début du tableau.</td> + </tr> + <tr> + <td><code>a.slice(start[, end])</code></td> + <td>Renvoie un sous-tableau.</td> + </tr> + <tr> + <td><code>a.sort([cmpfn])</code></td> + <td>Trie le tableau (avec une fonction de comparaison optionnelle).</td> + </tr> + <tr> + <td><code>a.splice(start, delcount[, item1[, ...[, itemN]]])</code></td> + <td>Permet de modifier un tableau en en supprimant une partie et en la remplaçant avec plus d'éléments.</td> + </tr> + <tr> + <td><code>a.reverse()</code></td> + <td>Retourne le tableau.</td> + </tr> + </tbody> </table> -<h2 id="Les_fonctions">Les fonctions</h2> +<h2 id="functions">Les fonctions</h2> -<p>Avec les objets, les fonctions sont les composants de base d'une bonne compréhension de JavaScript. La fonction la plus basique n'a rien de compliqué :</p> +<p>Avec les objets, les fonctions sont les composants de base d'une bonne compréhension de JavaScript. La fonction la plus basique n'a rien de compliqué :</p> -<pre class="brush: js notranslate">function ajoute(x, y) { +<pre class="brush: js">function ajoute(x, y) { var total = x + y; return total; -} -</pre> +}</pre> <p>Ceci représente tout ce qu'il y a à savoir à propos des fonctions basiques. Une fonction JavaScript peut recevoir 0 paramètre nommé ou plus. Son corps peut contenir autant d'instructions que vous le voulez et permet de déclarer des variables qui sont locales à la fonction. L'instruction <code>return</code> peut être utilisée pour renvoyer une valeur à tout moment, mettant ainsi fin à la fonction. Si aucune instruction <code>return</code> n'est utilisée (ou que l'instruction <code>return</code> n'est suivie d'aucune valeur), JavaScript renvoie <code>undefined</code>.</p> <p>On se rendra compte que les paramètres sont plus des indications qu'autre chose. Il est en effet possible d'appeler une fonction sans lui fournir les paramètres qu'elle attend, auquel cas ils vaudront <code>undefined</code>.</p> -<pre class="brush: js notranslate">ajoute(); // NaN - Il n'est pas possible d'additionner des variables indéfinies -</pre> +<pre class="brush: js">ajoute(); // NaN +//Il n'est pas possible d'additionner des variables indéfinies</pre> -<p>Il est également possible de fournir plus de paramètres que demandé par la fonction :</p> +<p>Il est également possible de fournir plus de paramètres que demandé par la fonction :</p> -<pre class="brush: js notranslate">ajoute(2, 3, 4); // 5 -// les deux premiers sont additionnés ; 4 est ignoré -</pre> +<pre class="brush: js">ajoute(2, 3, 4); // 5 +// les deux premiers sont additionnés ; 4 est ignoré</pre> -<p>Par définition les fonctions ont accès à des variables supplémentaires à l'intérieur de leur corps, appelée <a href="/fr/docs/Web/JavaScript/Reference/Fonctions/arguments"><code>arguments</code></a>. Ce sont des objets semblables à un tableau qui conservent toutes les valeurs reçues par la fonction. Réécrivons la fonction <code>ajoute</code> pour recevoir autant de valeurs qu'on veut :</p> +<p>Par définition les fonctions ont accès à des variables supplémentaires à l'intérieur de leur corps, appelée <a href="/fr/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code></a>. Ce sont des objets semblables à un tableau qui conservent toutes les valeurs reçues par la fonction. Réécrivons la fonction <code>ajoute</code> pour recevoir autant de valeurs qu'on veut :</p> -<pre class="brush: js notranslate">function ajoute() { +<pre class="brush: js">function ajoute() { var somme = 0; for (var i = 0, j = arguments.length; i < j; i++) { somme += arguments[i]; @@ -616,24 +592,22 @@ a.length // 101 return somme; } -ajoute(2, 3, 4, 5); // 14 -</pre> +ajoute(2, 3, 4, 5); // 14</pre> -<p>Ce n'est cependant pas vraiment plus utile que d'écrire <code>2 + 3 + 4 + 5</code>. Écrivons plutôt une fonction de calcul de moyenne :</p> +<p>Ce n'est cependant pas vraiment plus utile que d'écrire <code>2 + 3 + 4 + 5</code>. Écrivons plutôt une fonction de calcul de moyenne :</p> -<pre class="brush: js notranslate">function moyenne() { +<pre class="brush: js">function moyenne() { var somme = 0; for (var i = 0, j = arguments.length; i < j; i++) { somme += arguments[i]; } return somme / arguments.length; } -moyenne(2, 3, 4, 5); // 3.5 -</pre> +moyenne(2, 3, 4, 5); // 3.5</pre> -<p>Avec la décomposition des arguments (ES2015/ES6) (cf. <a href="/fr/docs/Web/JavaScript/Reference/Fonctions/param%C3%A8tres_du_reste">les paramètres du reste</a>) et <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/let">let</a></code>, on pourrait écrire une version équivalente :</p> +<p>C'est assez utile, mais cela semble un peu verbeux. Pour réduire un peu plus ce code, nous pouvons envisager de substituer l'utilisation du tableau d'arguments par <a href="/fr/docs/Web/JavaScript/Reference/Functions/rest_parameters">la syntaxe des paramètres du reste</a>. De cette façon, nous pouvons passer un nombre quelconque d'arguments dans la fonction tout en gardant notre code minimal. L'opérateur <strong><i>rest parameter</i></strong> pour cette syntaxe est utilisé dans les listes de paramètres de fonctions avec le format : <strong>...variable</strong> et il inclura dans cette variable la liste entière des arguments non capturés avec lesquels la fonction a été appelée. Nous remplacerons également la boucle <strong>for</strong> par une boucle <strong>for...of</strong> pour retourner les valeurs dans notre variable.</p> -<pre class="brush: js notranslate">function moyenne(...args) { +<pre class="brush: js">function moyenne(...args) { var somme = 0; for (let valeur of args) { somme += valeur; @@ -642,63 +616,73 @@ moyenne(2, 3, 4, 5); // 3.5 } moyenne(2, 3, 4, 5); // 3.5</pre> -<div class="note"> -<p><strong>Note :<code> </code></strong>Avec les paramètres du reste, dans l'exemple précédent, <code>args</code> contient tous les arguments passés à la fonction. Si on avait utilisé <code>fonction moyenne(premiereValeur, ...args)</code>, <code>args</code> aurait alors contenu toutes les valeurs mais pas le premier argument.</p> +<div class="notecard note"> + <p><b>Note :</b></p> + <p>Avec les paramètres du reste, dans l'exemple précédent, <code>args</code> contient tous les arguments passés à la fonction. Si on avait utilisé <code>fonction moyenne(premiereValeur, ...args)</code>, <code>args</code> aurait alors contenu toutes les valeurs mais pas le premier argument.</p> </div> -<p>C'est très pratique, mais on rencontre un nouveau problème. La fonction <code>moyenne()</code> reçoit une liste de valeurs séparées par des virgules, mais comment fait-on si on souhaite trouver la moyenne des valeurs d'un tableau ?</p> +<p>C'est très pratique, mais on rencontre un nouveau problème. La fonction <code>moyenne()</code> reçoit une liste de valeurs séparées par des virgules, mais comment fait-on si on souhaite trouver la moyenne des valeurs d'un tableau ?</p> -<p>On pourrait simplement récrire la fonction comme ceci :</p> +<p>On pourrait simplement récrire la fonction comme ceci :</p> -<pre class="brush: js notranslate">function moyenneTableau(arr) { +<pre class="brush: js">function moyenneTableau(arr) { var somme = 0; for (var i = 0, j = arr.length; i < j; i++) { somme += arr[i]; } return somme / arr.length; } -moyenneTableau([2, 3, 4, 5]); // 3.5 -</pre> +moyenneTableau([2, 3, 4, 5]); // 3.5</pre> -<p>Mais ce serait bien si on pouvait réutiliser la fonction qu'on avait déjà créée. Par chance, JavaScript permet d'appeler une fonction et de lui donner un tableau de paramètres d'une longueur arbitraire, à l'aide de la méthode <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Function/apply"><code>apply()</code></a> de tout objet <code>Function</code>.</p> +<p>Mais ce serait bien si on pouvait réutiliser la fonction qu'on avait déjà créée. Par chance, JavaScript permet d'appeler une fonction et de lui donner un tableau de paramètres d'une longueur arbitraire, à l'aide de la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/apply"><code>apply()</code></a> de tout objet <code>Function</code>.</p> -<pre class="brush: js notranslate">moyenne.apply(null, [2, 3, 4, 5]); // 3.5 +<pre class="brush: js">moyenne.apply(null, [2, 3, 4, 5]); // 3.5 </pre> -<p>Le second paramètre envoyé à <code>apply()</code> est le tableau à utiliser comme paramètre ; nous parlerons du premier plus tard. Cela permet de souligner le fait que les fonctions sont aussi des objets.</p> +<p>Le second paramètre envoyé à <code>apply()</code> est le tableau à utiliser comme paramètre ; nous parlerons du premier plus tard. Cela permet de souligner le fait que les fonctions sont aussi des objets.</p> -<div class="note"> -<p><strong>Note :</strong> On peut également utiliser <a href="/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Op%C3%A9rateur_de_d%C3%A9composition">l'opérateur de décomposition</a> pour l'appel et la définition de la fonction pour écrire, par exemple, <code>moyenne(...nombres)</code>.</p> +<div class="notecard note"> + <p><b>Note :</b></p> + <p>On peut également utiliser <a href="/fr/docs/Web/JavaScript/Reference/Operators/Spread_syntax">l'opérateur de décomposition</a> pour l'appel et la définition de la fonction pour écrire, par exemple, <code>moyenne(...nombres)</code>.</p> </div> -<p>JavaScript permet également de créer des fonctions anonymes.</p> +<h3 id="anonymous_functions">Fonctions anonymes</h3> -<pre class="brush: js notranslate">var moyenne = function() { - var somme = 0; - for (var i = 0, j = arguments.length; i < j; i++) { +<p>JavaScript vous permet de créer des fonctions anonymes, c'est-à-dire des fonctions sans nom :</p> + +<pre class="brush: js">function() { + let somme = 0; + for (let i = 0, j = arguments.length; i < j; i++) { somme += arguments[i]; } return somme / arguments.length; -} -</pre> +};</pre> -<p>Ceci est sémantiquement équivalent à la forme <code>function moyenne()</code> vue plus haut. C'est extrêmement puissant, car cela permet de mettre une définition de fonction n'importe où, là où on mettrait normalement une expression. C'est la porte ouverte à toutes sortes d'astuces brillantes. Voici par exemple une manière de « cacher » certaines variables locales, comme la visibilité par blocs du langage C :</p> +<p>Mais une telle fonction anonyme n'est pas utile en soi, car sans nom, il n'y a aucun moyen d'appeler la fonction. En pratique, les fonctions anonymes sont donc généralement utilisées comme arguments pour d'autres fonctions ou sont rendues appelables en les assignant immédiatement à une variable qui peut être utilisée pour invoquer la fonction :</p> -<pre class="brush: js notranslate">var a = 1; -var b = 2; +<pre class="brush: js">let moyenne = function() { + let somme = 0; + for (let i = 0, j = arguments.length; i < j; i++) { + somme += arguments[i]; + } + return somme / arguments.length; +}</pre> -(function() { - var b = 3; - a += b; -})(); +<p>Cela rend la fonction anonyme invocable en appelant <code>moyenne()</code> avec certains arguments — c'est-à-dire que c'est sémantiquement équivalent à déclarer la fonction en utilisant la forme <code>fonction moyenne()</code> de fonction nommée.</p> -a; // 4 -b; // 2 -</pre> +<p>Mais les fonctions anonymes peuvent être utiles même si elles ne sont jamais affectées à des variables ou transmises comme arguments à d'autres fonctions : JavaScript fournit un mécanisme permettant de déclarer et d'invoquer simultanément une fonction à l'aide d'une seule expression. Cela s'appelle une <a href="/fr/docs/Glossary/IIFE">expression de fonction invoquée immédiatement (IIFE)</a>, et la syntaxe pour l'utiliser avec une fonction anonyme ressemble à ceci :</p> + +<pre class="brush: js">(function() { + // … +})();</pre> + +<p>De plus amples détails sur les IIFE sont hors de portée de cet article d'introduction — mais un bon exemple de ce à quoi ils sont particulièrement utiles se trouve dans la section <a href="/fr/docs/Web/JavaScript/Closures#emulating_private_methods_with_closures">Émulation de méthodes privées avec des fermetures</a> de l'article <a href="/fr/docs/Web/JavaScript/Closures">Fermetures</a>.</p> + +<h3 id="recursive_functions">Fonctions récursives</h3> <p>JavaScript permet d'appeler des fonctions récursivement. C'est particulièrement utile lorsqu'on a affaire à des structures en arbre, comme c'est le cas dans le DOM du navigateur.</p> -<pre class="brush: js notranslate">function countChars(elm) { +<pre class="brush: js">function countChars(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } @@ -707,12 +691,11 @@ b; // 2 count += countChars(child); } return count; -} -</pre> +}</pre> -<p>Cela permet de mettre le doigt sur un problème potentiel des fonctions anonymes : comment les appelle-t-on récursivement si elles n'ont pas de nom ? La réponse se trouve une nouvelle fois dans l'objet <code>arguments</code>, qui, non content d'être une liste des paramètres, fournit également une propriété appelée <code>arguments.callee</code>. Celle-ci se réfère toujours à la fonction courante et peut donc être utilisée pour des appels récursifs :</p> +<p>Cela met en évidence un problème potentiel avec les fonctions anonymes : comment les appeler de manière récursive si elles n'ont pas de nom ? JavaScript vous permet de nommer les expressions de fonctions pour cela. Vous pouvez utiliser des <a href="/fr/docs/Glossary/IIFE">IIFE (« Immediately Invoked Function Expressions » en anglais soit « Expressions de fonctions immédiatement invoquées » en français)</a> nommées, comme indiqué ci-dessous :</p> -<pre class="brush: js notranslate">var charsInBody = (function counter(elm) { +<pre class="brush: js">var charsInBody = (function counter(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } @@ -723,25 +706,24 @@ b; // 2 return count; })(document.body);</pre> -<p>La forme utilisée dans l'exemple qui précède est <a href="/fr/docs/Glossaire/IIFE">une fonction invoquée immédiatement</a>. On déclare une fonction qu'on appelle directement. Le nom <code>counter</code> n'est alors accessible qu'au sein de la portée.</p> - <p>Le nom fourni à l'expression de la fonction n'est disponible qu'au sein de la portée de la fonction. Cela permet au moteur JavaScript de faire des optimisations. Cela rend également le code plus lisible. Le nom apparaîtra également dans le débogueur et les piles d'appel, ce qui permettra de gagner du temps.</p> <p>En JavaScript, les fonctions sont également des objets. Il est donc possible de leur ajouter ou de modifier leurs propriétés.</p> -<h2 id="Les_objets_personnalisés">Les objets personnalisés</h2> +<h2 id="custom_objects">Les objets personnalisés</h2> -<div class="note"> -<p><strong>Note :</strong> Pour une approche plus détaillée de la programmation orientée objet en JavaScript, voir l'<a href="/fr/docs/Web/JavaScript/Introduction_à_JavaScript_orienté_objet">Introduction à JavaScript orienté objet</a>.</p> +<div class="notecard note"> + <p><b>Note :</b></p> + <p>Pour une approche plus détaillée de la programmation orientée objet en JavaScript, voir l'<a href="/fr/docs/conflicting/Learn/JavaScript/Objects">Introduction à JavaScript orienté objet</a>.</p> </div> -<p>Dans la programmation orientée objet classique, les objets sont des collections de données et de méthodes opérant sur ces données. Imaginons un objet personne avec les champs prénom et nom. Il y a deux manières d'afficher son nom complet : de la façon « prénom nom » ou de la façon « nom prénom ». À l'aide des fonctions et des objets vus précédemment, voici une manière de le faire :</p> +<p>Dans la programmation orientée objet classique, les objets sont des collections de données et de méthodes opérant sur ces données. Imaginons un objet personne avec les champs prénom et nom. Il y a deux manières d'afficher son nom complet : de la façon « prénom nom » ou de la façon « nom prénom ». À l'aide des fonctions et des objets vus précédemment, voici une manière de le faire :</p> -<pre class="bad-example brush: js notranslate">function creerPersonne(prenom, nom) { +<pre class="bad-example brush: js">function creerPersonne(prenom, nom) { return { prenom: prenom, nom: nom - } + }; } function personneNomComplet(personne) { @@ -752,14 +734,13 @@ function personneNomCompletInverse(personne) { return personne.nom + ' ' + personne.prenom; } -var s = creerPersonne("Simon", "Willison"); +let s = creerPersonne("Simon", "Willison"); personneNomComplet(s); // Simon Willison - personneNomCompletInverse(s); // Willison Simon</pre> -<p>Ça fonctionne, mais c'est inutilement verbeux. On va se retrouver avec des dizaines de fonctions dans l'espace de noms global. Ce dont on aurait vraiment besoin, c'est d'une manière d'attacher une fonction à un objet. Comme les fonctions sont des objets, c'est facile :</p> +<p>Ça fonctionne, mais c'est inutilement verbeux. On va se retrouver avec des dizaines de fonctions dans l'espace de noms global. Ce dont on aurait vraiment besoin, c'est d'une manière d'attacher une fonction à un objet. Comme les fonctions sont des objets, c'est facile :</p> -<pre class="brush: js notranslate">function creerPersonne(prenom, nom) { +<pre class="brush: js">function creerPersonne(prenom, nom) { return { prenom: prenom, nom: nom, @@ -769,25 +750,26 @@ personneNomCompletInverse(s); // Willison Simon</pre> nomCompletInverse: function() { return this.nom + ' ' + this.prenom; } - } + }; } -var s = creerPersonne("Simon", "Willison") +let s = creerPersonne("Simon", "Willison") s.nomComplet(); // Simon Willison s.nomCompletInverse(); // Willison Simon</pre> -<p>Il y a quelque chose que nous n'avons pas vu jusqu'à présent : le mot-clé <code><a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/L_opérateur_this">this</a></code>. Utilisé au sein d'une fonction, <code>this</code> fait référence à l'objet courant. Sa signification dépend de la façon dont la fonction a été appelée. Si elle a été appelée avec <a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_de_membres">la notation utilisant le point ou les crochets</a> sur un objet, cet objet devient <code>this</code>. Si cette notation n'a pas été utilisée pour l'appel, <code>this</code> fera référence à l'objet global. C'est une source fréquente d'erreurs. Par exemple :</p> +<p>Il y a quelque chose que nous n'avons pas vu jusqu'à présent : le mot-clé <a href="/fr/docs/Web/JavaScript/Reference/Operators/this"><code>this</code></a>. Utilisé au sein d'une fonction, <code>this</code> fait référence à l'objet courant. Sa signification dépend de la façon dont la fonction a été appelée. Si elle a été appelée avec <a href="/fr/docs/Web/JavaScript/Reference/Operators/Object_initializer#accessing_properties">la notation utilisant le point ou les crochets</a> sur un objet, cet objet devient <code>this</code>. Si cette notation n'a pas été utilisée pour l'appel, <code>this</code> fera référence à l'objet global.</p> + +<p>C'est une source fréquente d'erreurs. Par exemple :</p> -<pre class="brush: js notranslate">var s = creerPersonne("Simon", "Willison"); +<pre class="brush: js">var s = creerPersonne("Simon", "Willison"); var nomComplet = s.nomComplet; -nomComplet(); // undefined undefined -</pre> +nomComplet(); // undefined undefined</pre> <p>Lorsqu'on appelle <code>nomComplet()</code>, <code>this</code> est lié à l'objet global. Comme il n'y a pas de variables globales appelées <code>prenom</code> ou <code>nom</code>, on se retrouve avec <code>undefined</code> pour chacune.</p> -<p>On peut se servir du mot clé <code>this</code> pour améliorer notre fonction <code>créerPersonne</code> :</p> +<p>On peut se servir du mot-clé <code>this</code> pour améliorer notre fonction <code>créerPersonne</code> :</p> -<pre class="brush: js notranslate">function Personne(prenom, nom) { +<pre class="brush: js">function Personne(prenom, nom) { this.prenom = prenom; this.nom = nom; this.nomComplet = function() { @@ -797,14 +779,15 @@ nomComplet(); // undefined undefined return this.nom + ' ' + this.prenom; } } -var s = new Personne("Simon", "Willison"); -</pre> +var s = new Personne("Simon", "Willison");</pre> -<p>Nous avons utilisé un nouveau mot clé : <code><a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/L_opérateur_new">new</a></code>. <code>new</code> est très lié à <code>this</code>. Il crée un nouvel objet vide et appelle ensuite la fonction spécifiée, avec <code>this</code> pointant vers ce nouvel objet. Les fonctions prévues pour être appelées par <code>new</code> sont appelées des constructeurs. L'usage courant est de mettre la première lettre de ces fonctions en majuscule pour se souvenir de les appeler avec <code>new</code>.</p> +<p>Nous avons utilisé un nouveau mot clé : <a href="/fr/docs/Web/JavaScript/Reference/Operators/new"><code>new</code></a>. <code>new</code> est très lié à <code>this</code>. Il crée un nouvel objet vide et appelle ensuite la fonction spécifiée, avec <code>this</code> pointant vers ce nouvel objet. Les fonctions prévues pour être appelées par <code>new</code> sont appelées des constructeurs. L'usage courant est de mettre la première lettre de ces fonctions en majuscule pour se souvenir de les appeler avec <code>new</code>.</p> -<p>Nos objets <code>Personne</code> s'améliorent, mais il leur reste certaines aspérités pas très esthétiques. Chaque fois que l'on crée une personne, on crée deux nouveaux objets de fonctions en même temps. Ne serait-ce pas mieux si ce code était partagé ?</p> +<p>La fonction améliorée présente toujours le même écueil avec l'appel de <code>personneNomComplet()</code> seul.</p> -<pre class="brush: js notranslate">function personneNomComplet() { +<p>Nos objets <code>Personne</code> s'améliorent, mais il leur reste certaines aspérités pas très esthétiques. Chaque fois que l'on crée une personne, on crée deux nouveaux objets de fonctions en même temps. Ne serait-ce pas mieux si ce code était partagé ?</p> + +<pre class="brush: js">function personneNomComplet() { return this.prenom + ' ' + this.nom; } @@ -817,41 +800,38 @@ function Personne(prenom, nom) { this.nom = nom; this.nomComplet = personneNomComplet; this.nomCompletInverse = personneNomCompletInverse; -} -</pre> +}</pre> -<p>C'est mieux : on crée les fonctions une seule fois, et on leur assigne des références au sein du constructeur. Est-il possible de faire encore mieux que ça ? La réponse est oui :</p> +<p>C'est mieux : on crée les fonctions une seule fois, et on leur assigne des références au sein du constructeur. Est-il possible de faire encore mieux que ça ? La réponse est oui :</p> -<pre class="brush: js notranslate">function Personne(prenom, nom) { +<pre class="brush: js">function Personne(prenom, nom) { this.prenom = prenom; this.nom = nom; } Personne.prototype.nomComplet = function() { - return this.prenom + ' ' + this.nom; + return this.prenom + ', ' + this.nom; } -Personne.prototype.nomCompletInverse = function nomCompletInverse() { - return this.nom + ' ' + this.prenom; -} -</pre> +Personne.prototype.nomCompletInverse = function() { + return this.nom + ', ' + this.prenom; +}</pre> -<p><code>Personne.prototype</code> est un objet partagé par toutes les instances de <code>Personne</code>. Il fait partie d'une chaîne de résolution (qui a un nom spécial, la « chaîne de prototypes ») : chaque fois que vous essayez d'accéder à une propriété de <code>Personne</code> qui n'est pas définie, JavaScript va vérifier <code>Personne.prototype</code> pour voir si cette propriété n'existe pas plutôt à cet endroit. Par conséquent, tout ce qui est assigné à <code>Personne.prototype</code> devient disponible à toutes les instances de ce constructeur via l'objet <code>this</code>.</p> +<p><code>Personne.prototype</code> est un objet partagé par toutes les instances de <code>Personne</code>. Il fait partie d'une chaîne de résolution (qui a un nom spécial, la « chaîne de prototypes ») : chaque fois que vous essayez d'accéder à une propriété de <code>Personne</code> qui n'est pas définie, JavaScript va vérifier <code>Personne.prototype</code> pour voir si cette propriété n'existe pas plutôt à cet endroit. Par conséquent, tout ce qui est assigné à <code>Personne.prototype</code> devient disponible à toutes les instances de ce constructeur via l'objet <code>this</code>.</p> -<p>C'est un outil incroyablement puissant. JavaScript vous permet de modifier le prototype de quelque chose à tout moment dans votre programme, cela signifie qu'il est possible d'ajouter des méthodes supplémentaires à des objets existants lors de l'exécution :</p> +<p>C'est un outil incroyablement puissant. JavaScript vous permet de modifier le prototype de quelque chose à tout moment dans votre programme, cela signifie qu'il est possible d'ajouter des méthodes supplémentaires à des objets existants lors de l'exécution :</p> -<pre class="brush: js notranslate">var s = new Personne("Simon", "Willison"); +<pre class="brush: js">var s = new Personne("Simon", "Willison"); s.prenomEnMajuscules(); // TypeError on line 1: s.prenomEnMajuscules is not a function Personne.prototype.prenomEnMajuscules = function prenomEnMajuscules() { return this.prenom.toUpperCase() } -s.prenomEnMajuscules(); // "SIMON" -</pre> +s.prenomEnMajuscules(); // "SIMON"</pre> -<p>Il est également possible d'ajouter des choses aux prototypes de classes d'objets JavaScript prédéfinies. Ajoutons par exemple une méthode à <code>String</code> qui renvoie cette chaîne à l'envers :</p> +<p>Il est également possible d'ajouter des choses aux prototypes de classes d'objets JavaScript prédéfinies. Ajoutons par exemple une méthode à <code>String</code> qui renvoie cette chaîne à l'envers :</p> -<pre class="brush: js notranslate">var s = "Simon"; +<pre class="brush: js">var s = "Simon"; s.inverse(); // TypeError on line 1: s.inverse is not a function String.prototype.inverse = function inverse() { @@ -861,47 +841,43 @@ String.prototype.inverse = function inverse() { } return r; } -s.inverse(); // "nomiS" -</pre> +s.inverse(); // "nomiS"</pre> -<p>Notre nouvelle méthode fonctionne même sur les chaînes littérales !</p> +<p>Notre nouvelle méthode fonctionne même sur les chaînes littérales !</p> -<pre class="brush: js notranslate">"Ceci peut maintenant être inversé.".inverse() // ".ésrevni ertê tnanetniam tuep iceC" -</pre> +<pre class="brush: js">"Ceci peut maintenant être inversé.".inverse() // ".ésrevni ertê tnanetniam tuep iceC"</pre> -<p>Comme mentionné précédemment, le prototype fait partie d'une chaîne de prototypes. Le début de cette chaîne est <code>Object.prototype</code>, dont <code>toString()</code> fait partie des méthodes. C'est cette méthode qui est appelée quand vous essayez de représenter un objet sous la forme d'une chaîne. Elle sera utile pour déboguer nos objets <code>Personne</code> :</p> +<p>Comme mentionné précédemment, le prototype fait partie d'une chaîne de prototypes. Le début de cette chaîne est <code>Object.prototype</code>, dont <code>toString()</code> fait partie des méthodes. C'est cette méthode qui est appelée quand vous essayez de représenter un objet sous la forme d'une chaîne. Elle sera utile pour déboguer nos objets <code>Personne</code> :</p> -<pre class="brush: js notranslate">var s = new Personne("Simon", "Willison"); +<pre class="brush: js">var s = new Personne("Simon", "Willison"); s; // [object Object] Personne.prototype.toString = function() { - return '<Personne : ' + this.nomComplet() + '>'; + return '<Personne : ' + this.nomComplet() + '>'; } -s.toString(); // "<Personne : Simon Willison>" -</pre> +s.toString(); // "<Personne : Simon Willison>"</pre> -<p>Vous vous souvenez de la fonction <code>moyenne.apply()</code> qui avait un premier paramètre défini à <code>null</code> ? Nous pouvons en reparler à présent. Le premier paramètre d'<code>apply()</code> est l'objet qui doit être traité comme <code>this</code>. Par exemple, voici une implémentation de <code>new</code> :</p> +<p>Vous vous souvenez de la fonction <code>moyenne.apply()</code> qui avait un premier paramètre défini à <code>null</code> ? Nous pouvons en reparler à présent. Le premier paramètre d'<code>apply()</code> est l'objet qui doit être traité comme <code>this</code>. Par exemple, voici une implémentation de <code>new</code> :</p> -<pre class="brush: js notranslate">function trivialNew(constructor, ...args) { +<pre class="brush: js">function trivialNew(constructor, ...args) { var o = {}; // Crée un objet constructor.apply(o, ...args); return o; -} -</pre> +}</pre> -<p>Ce n'est pas une réplique exacte de <code>new</code> parce qu'elle n'initialise pas la chaîne de prototype. La méthode <code>apply()</code> est difficile à illustrer, ce n'est pas quelque chose qu'on utilise très souvent, mais c'est utile de savoir qu'elle existe. Dans ce fragment de code, on utilise les <a href="/fr/docs/Web/JavaScript/Reference/Fonctions/param%C3%A8tres_du_reste">arguments restants</a>, représentés par <code>...args</code>. Comme son nom l'indique, cela représente le reste des arguments passés à la fonction. À l'heure actuelle, cette fonctionnalité n'est disponible que sous Firefox, il est donc conseillé d'utiliser <code>arguments</code>.</p> +<p>Ce n'est pas une réplique exacte de <code>new</code> parce qu'elle n'initialise pas la chaîne de prototype. La méthode <code>apply()</code> est difficile à illustrer, ce n'est pas quelque chose qu'on utilise très souvent, mais c'est utile de savoir qu'elle existe. Dans ce fragment de code, on utilise les <a href="/fr/docs/Web/JavaScript/Reference/Functions/rest_parameters">arguments restants</a>, représentés par <code>...args</code>. Comme son nom l'indique, cela représente le reste des arguments passés à la fonction. À l'heure actuelle, cette fonctionnalité n'est disponible que sous Firefox, il est donc conseillé d'utiliser <code>arguments</code>.</p> <p>Appeler</p> -<pre class="brush: js notranslate">var bill = trivialNew(Personne, ["William", "Orange"]);</pre> +<pre class="brush: js">var bill = trivialNew(Personne, ["William", "Orange"]);</pre> -<p>est donc quasiment équivalent à :</p> +<p>est donc quasiment équivalent à :</p> -<pre class="brush: js notranslate">var bill = new Personne("William", "Orange");</pre> +<pre class="brush: js">var bill = new Personne("William", "Orange");</pre> -<p><code>apply()</code> possède une fonction proche, appelée <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Function/call"><code>call</code></a>, qui permet de définir la valeur de <code>this</code> mais qui prend une liste d'arguments plutôt qu'un tableau.</p> +<p><code>apply()</code> possède une fonction proche, appelée <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/call"><code>call</code></a>, qui permet de définir la valeur de <code>this</code> mais qui prend une liste d'arguments plutôt qu'un tableau.</p> -<pre class="brush: js notranslate">function nomMajuscule() { +<pre class="brush: js">function nomMajuscule() { return this.nom.toUpperCase(); } var s = new Personne("Simon", "Willison"); @@ -909,29 +885,28 @@ nomMajuscule.call(s); // correspond à: s.nomMajuscule = nomMajuscule; s.nomMajuscule();</pre> -<h2 id="Les_fonctions_internes">Les fonctions internes</h2> +<h2 id="inner_functions">Les fonctions internes</h2> -<p>Comme nous l'avons déjà vu, les déclarations de fonctions JavaScript peuvent se trouver à l'intérieur d'autres fonctions. Un détail important des fonctions définies à l'intérieur d'autres fonctions est qu'elles peuvent accéder à des variables de leur fonction parente :</p> +<p>Comme nous l'avons déjà vu, les déclarations de fonctions JavaScript peuvent se trouver à l'intérieur d'autres fonctions. Un détail important des fonctions définies à l'intérieur d'autres fonctions est qu'elles peuvent accéder à des variables de leur fonction parente :</p> -<pre class="brush: js notranslate">function parentFunc() { +<pre class="brush: js">function parentFunc() { var a = 1; function fonctionImbriquee() { var b = 4; // Inacessible depuis parentFunc() return a + b; } return fonctionImbriquee(); // 5 -} -</pre> +}</pre> -<p>Cela peut s'avérer très utile dans l'écriture de code plus facilement maintenable. Si une fonction A dépend d'une ou deux autres fonctions B et C qui ne sont utiles à aucun autre endroit de votre code, on peut imbriquer ces fonctions utilitaires B et C à l'intérieure de la fonction A. Cela diminue le nombre de fonctions se trouvant dans la portée globale, ce qui est toujours une bonne chose.</p> +<p>Cela peut s'avérer très utile dans l'écriture de code plus facilement maintenable. Si une fonction A dépend d'une ou deux autres fonctions B et C qui ne sont utiles à aucun autre endroit de votre code, on peut imbriquer ces fonctions utilitaires B et C à l'intérieur de la fonction A. Cela diminue le nombre de fonctions se trouvant dans la portée globale, ce qui est toujours une bonne chose.</p> -<p>C'est également un bon moyen de se préserver de l'attrait trompeur des variables globales. Lorsqu'on écrit du code complexe, il est souvent tentant d'utiliser des variables globales pour partager des valeurs entre différentes fonctions, ce qui mène à du code difficile à maintenir. Les fonctions internes peuvent partager des variables avec leur parent, de sorte que vous pouvez utiliser ce mécanisme pour coupler des fonctions ensemble lorsque cela a un sens, sans pour autant polluer l'espace de noms global. Ce sont ainsi des « globales locales ». Cette technique doit être utilisée parcimonieusement, mais il est utile de s'en souvenir.</p> +<p>C'est également un bon moyen de se préserver de l'attrait trompeur des variables globales. Lorsqu'on écrit du code complexe, il est souvent tentant d'utiliser des variables globales pour partager des valeurs entre différentes fonctions, ce qui mène à du code difficile à maintenir. Les fonctions internes peuvent partager des variables avec leur parent, de sorte que vous pouvez utiliser ce mécanisme pour coupler des fonctions ensemble lorsque cela a un sens, sans pour autant polluer l'espace de noms global. Ce sont ainsi des « globales locales ». Cette technique doit être utilisée parcimonieusement, mais il est utile de s'en souvenir.</p> -<h2 id="Les_fermetures_Closures">Les fermetures (<em>Closures</em>)</h2> +<h2 id="closures">Les fermetures (<em>Closures</em>)</h2> -<p>Cela nous amène à l'une des abstractions les plus spectaculaires que JavaScript a à nous offrir. C'est également un des concepts les plus déroutants. Que fait ce fragment de code ?</p> +<p>Cela nous amène à l'une des abstractions les plus spectaculaires que JavaScript a à nous offrir. C'est également un des concepts les plus déroutants. Que fait ce fragment de code ?</p> -<pre class="brush: js notranslate">function creerAdditionneur(a) { +<pre class="brush: js">function creerAdditionneur(a) { return function(b) { return a + b; } @@ -939,23 +914,19 @@ s.nomMajuscule();</pre> var ajoute5 = creerAdditionneur(5); var ajoute20 = creerAdditionneur(20); ajoute5(6); // ? -ajoute20(7); // ? -</pre> +ajoute20(7); // ?</pre> -<p>Le nom de la fonction <code>creerAdditionneur</code> devrait vous donner un indice : elle crée de nouveaux additionneurs sous forme de fonctions qui, quand elles sont appelées avec un paramètre, l'ajoutent à celui avec lequel elles ont été créées.</p> +<p>Le nom de la fonction <code>creerAdditionneur</code> devrait vous donner un indice : elle crée de nouveaux additionneurs sous forme de fonctions qui, quand elles sont appelées avec un paramètre, l'ajoutent à celui avec lequel elles ont été créées.</p> -<p>Ce qui se passe ici est sensiblement la même chose qu'avec les fonctions internes dont nous avons parlé précédemment : une fonction définie à l'intérieur d'une autre fonction a accès aux variables de sa fonction extérieure. La seule différence ici est que la fonction extérieure a déjà renvoyé son résultat, et le bon sens semblerait vouloir être que ses variables locales n'existent plus. Mai<em>s</em> elles existent <em>encore</em> ; autrement les additionneurs présentés ci-dessus ne fonctionneraient pas. Ce n'est pas tout, il y a même deux « copies » différentes des variables locales de <code>creerAdditionneur</code> : une dans laquelle <code>a</code> vaut 5 et une autre dans laquelle <code>a</code> vaut 20. Quel est donc le résultat de ces appels de fonction ?</p> - -<pre class="brush: js notranslate">ajoute5(6); // renvoie 11 -ajoute20(7); // renvoie 27 -</pre> +<p>Ce qui se passe ici est sensiblement la même chose qu'avec les fonctions internes dont nous avons parlé précédemment : une fonction définie à l'intérieur d'une autre fonction a accès aux variables de sa fonction extérieure. La seule différence ici est que la fonction extérieure a déjà renvoyé son résultat, et le bon sens semblerait vouloir être que ses variables locales n'existent plus. Mai<em>s</em> elles existent <em>encore</em> ; autrement les additionneurs présentés ci-dessus ne fonctionneraient pas. Ce n'est pas tout, il y a même deux « copies » différentes des variables locales de <code>creerAdditionneur</code> : une dans laquelle <code>a</code> vaut 5 et une autre dans laquelle <code>a</code> vaut 20. Quel est donc le résultat de ces appels de fonction ?</p> -<p>Voici ce qui se passe en réalité. Lorsque JavaScript exécute une fonction, un objet de portée est créé pour conserver les variables locales créées au sein de cette fonction. Il est initialisé avec les variables passées en paramètres à la fonction. Cela ressemble à l'objet global dans lequel toutes les variables et fonctions globales se trouvent, mais avec quelques différences importantes : premièrement, un nouvel objet de portée est créé chaque fois qu'une fonction commence à s'exécuter, et deuxièmement, contrairement à l'objet global (qui, dans le navigateur, correspond à l'objet <code>window</code>), on ne peut pas directement accéder à ces objets de portée depuis le code JavaScript. Il n'existe pas de mécanisme permettant de parcourir les propriétés de l'objet de la portée courante par exemple.</p> +<pre class="brush: js">ajoute5(6); // renvoie 11 +ajoute20(7); // renvoie 27</pre> -<p>Donc, quand <code>creerAdditionneur</code> est appelée, une portée est créée avec une propriété : <code>a</code>, qui est le paramètre passé à la fonction <code>creerAdditionneur</code>. Celle-ci renvoie alors une fonction nouvellement créée. Normalement, le ramasse-miettes de JavaScript devrait supprimer l'objet de visibilité créé pour <code>creerAdditionneur</code> à ce moment, mais la fonction renvoyée garde une référence vers cet objet de visibilité. Par conséquent, il ne sera pas supprimé par le ramasse-miettes tant qu'il y a toujours des références à l'objet de type <code>function</code> que <code>creerAdditionneur</code> a renvoyé.</p> +<p>Voici ce qui se passe en réalité. Lorsque JavaScript exécute une fonction, un objet de portée est créé pour conserver les variables locales créées au sein de cette fonction. Il est initialisé avec les variables passées en paramètres à la fonction. Cela ressemble à l'objet global dans lequel toutes les variables et fonctions globales se trouvent, mais avec quelques différences importantes : premièrement, un nouvel objet de portée est créé chaque fois qu'une fonction commence à s'exécuter, et deuxièmement, contrairement à l'objet global (qui, dans le navigateur, correspond à l'objet <code>window</code>), on ne peut pas directement accéder à ces objets de portée depuis le code JavaScript. Il n'existe pas de mécanisme permettant de parcourir les propriétés de l'objet de la portée courante par exemple.</p> -<p>Certains objets de portée forment une chaîne appelée la chaîne de portées, semblable à la chaîne de prototypes utilisée par le système objet de JavaScript.</p> +<p>Donc, quand <code>creerAdditionneur()</code> est appelée, une portée est créée avec une propriété : <code>a</code>, qui est le paramètre passé à la fonction <code>creerAdditionneur()</code>. Celle-ci renvoie alors une fonction nouvellement créée. Normalement, le ramasse-miettes de JavaScript devrait supprimer l'objet de visibilité créé pour <code>creerAdditionneur()</code> à ce moment, mais la fonction renvoyée garde une référence vers cet objet de visibilité. Par conséquent, il ne sera pas supprimé par le ramasse-miettes tant qu'il y a toujours des références à l'objet de type fonction que <code>creerAdditionneur()</code> a renvoyé.</p> -<p>Ce qu'on appelle une <strong>fermeture</strong> est la combinaison d'une fonction et de l'objet de portée dans lequel elle a été créée.</p> +<p>Les objets Scope forment une chaîne appelée chaîne de portée, similaire à la chaîne de prototype utilisée par le système d'objets de JavaScript.</p> -<p>Les fermetures permettent des enregistrements d'état et, en tant que telles, peuvent souvent être utilisées à la place d'objets. Vous pourrez trouver plus d'informations sur les fermetures dans <a href="/fr/docs/Web/JavaScript/Guide/Closures">cet article</a>.</p> +<p>Une <strong>fermeture</strong> est la combinaison d'une fonction et de la portée de l'objet dans lequel elle a été créée. Les fermetures vous permettent de sauvegarder l'état — en tant que telles, elles peuvent souvent être utilisées à la place des objets. Vous pouvez trouver <a href="http://stackoverflow.com/questions/111102/how-do-javascript-closures-work">plusieurs excellentes introductions aux fermetures dans cet article</a>.</p> |