UNPKG

nodebook

Version:

Node.js • Apprendre par la pratique. Familiarisez-vous avec JavaScript, Node.js et l'écosystème de modules npm. Apprenez à concevoir et à déployer des *applications web* et des *outils en ligne de commande*.

1,386 lines (1,296 loc) 357 kB
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="Asciidoctor 2.0.9"> <title>Jouer avec JavaScript</title> <style> #header, #content, #footer { margin: 2rem auto; max-width: 46rem; } #header { margin-top: 0; } .title, #toctitle { color: var(--dark-accent); } a { /* white-space: nowrap; */ } img, iframe, video, audio { max-width: 100%; } p { font-weight: normal; } /* Taken out from book.css */ dl dt { margin-bottom: 0.3125em; font-weight: bold; } dl dd { margin-bottom: 1.25em; } dt, th.tableblock, td.content, div.footnote { text-rendering: optimizeLegibility; } .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { overflow: auto; word-wrap: break-word; } .literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; } .listingblock { margin: 0 0 2em; } .listingblock > .content { position: relative; } .listingblock > .title { font-weight: bold; } .listingblock code[data-lang]::before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 1em; right: 1em; line-height: 1; text-transform: uppercase; color: #999; } .listingblock:hover code[data-lang]::before { display: block; } .listingblock.terminal pre .command::before { content: attr(data-prompt); padding-right: 0.5em; color: #999; } td.hdlist1, td.hdlist2 { vertical-align: top; padding-right: 0.625em; } td.hdlist1 { font-weight: bold; } .literalblock + .colist, .listingblock + .colist { margin-top: -1.5em; } .colist td:not([class]):first-child { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; } .colist td:not([class]):first-child img { max-width: none; } .colist td:not([class]):last-child { padding: 0.25em 0; } /* Custom classes */ .line-through { text-decoration: line-through; } .RemarquePreTitre, #toctitle { font-style: normal; font-weight: bold; } .RemarquePreTitre::after { content: "•"; padding-left: 5px; } .admonitionblock { } .admonitionblock > table, .exampleblock { --commented: rgba(17, 17, 68, .65); --border-radius-base: 8px; background-color: #fafafa; border: 1px solid var(--dark-shade); border-left: none; border-right: none; margin: 1.5em 0; padding: 1em; } .exampleblock .title { font-weight: bold; } .icon .title { font-size: 2em; } .admonitionblock > table td.icon { display: none; vertical-align: middle; } @media screen and (min-width: 769px) { .admonitionblock > table td.icon { display: table-cell; } } .admonitionblock > table td.icon { padding-right: 1em; } .admonitionblock > table td.icon img { max-width: none; } .colist ol { margin-left: 1.5em; /* aligns with the listing edge */ padding-left: 0; font-weight: bold; /* makes it stand out more */ } .colist ol p { margin: 0 0 .5em; } .listingblock:not(.prismjs) pre, .language-bash.hljs { background: #323232; color: wheat; margin: 0; padding: 1rem; } .language-bash.hljs .hljs-built_in, .language-bash.hljs .hljs-builtin-name { color: white; } .language-bash.hljs .hljs-string { color: lightgreen; } .language-bash.hljs .hljs-variable { color: lightskyblue; } .keyseq { font-weight: normal; white-space: nowrap; } .language-bash.hljs .keyseq { color: white; } .language-bash.hljs kbd { background: transparent; box-shadow: none; color: white; font-size: 0.8em; font-weight: bold; padding: 0.1em 0.4em; } .listingblock pre.highlightjs, .listingblock pre.prismjs { background-color: transparent; margin: 0; padding: 0; } .listingblock pre.highlightjs > code, .listingblock pre.prismjs { border-left: 4px solid var(--dark-accent); padding-left: 1em; font-size: .8em; } .listingblock pre.highlightjs > code.language-bash { border-left-color: limegreen; } .token.comment .conum { font-weight: normal; } .hdlist .hdlist1 { text-align: right; white-space: nowrap; } td > p:first-child { margin-top: 0; } .hljs-comment { font-style: normal !important; } #toc.toc2 a { text-decoration: none; white-space: normal; } #toc.toc2 a:hover, #toc.toc2 a:focus { text-decoration: underline; } #toc.toc2 ul { list-style: none; } #toc.toc2 > ul { padding-left: 0; } #toc.toc2 ul ul { padding-left: 1em; } @media screen and (min-width: 769px) { body { padding-left: 25vw !important; } #header, #content, #footer { margin-left: 0; } #toc.toc2 { height: 100%; left: 0; max-width: 20vw; overflow: auto; padding: 1rem; position: fixed; top: 0; z-index: 1000; } #toc.toc2 > ul { font-size: 0.85em; } #toc li.active > a[href^="#"], [id]:target { background: #ffc; } } .admonitionblock.context-callout > table { border-width: 5px; border-color: var(--brand-color); } </style> <style type="text/css" class="prism-theme">/** * prism.js default theme for JavaScript, CSS and HTML * Based on dabblet (http://dabblet.com) * @author Lea Verou */ code[class*="language-"], pre[class*="language-"] { color: black; background: none; text-shadow: 0 1px white; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { text-shadow: none; background: #b3d4fc; } pre[class*="language-"]::selection, pre[class*="language-"] ::selection, code[class*="language-"]::selection, code[class*="language-"] ::selection { text-shadow: none; background: #b3d4fc; } @media print { code[class*="language-"], pre[class*="language-"] { text-shadow: none; } } /* Code blocks */ pre[class*="language-"] { padding: 1em; margin: .5em 0; overflow: auto; } :not(pre) > code[class*="language-"], pre[class*="language-"] { background: #f5f2f0; } /* Inline code */ :not(pre) > code[class*="language-"] { padding: .1em; border-radius: .3em; white-space: normal; } .token.comment, .token.prolog, .token.doctype, .token.cdata { color: slategray; } .token.punctuation { color: #999; } .namespace { opacity: .7; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: #905; } .token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: #690; } .token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string { color: #9a6e3a; background: hsla(0, 0%, 100%, .5); } .token.atrule, .token.attr-value, .token.keyword { color: #07a; } .token.function, .token.class-name { color: #DD4A68; } .token.regex, .token.important, .token.variable { color: #e90; } .token.important, .token.bold { font-weight: bold; } .token.italic { font-style: italic; } .token.entity { cursor: help; } </style> <link rel="stylesheet" href="https://oncletom.io/styles/blog.css?v=v3.3.2"> <!-- WebMentions --> <link rel="pingback" href="https://webmention.io/oncletom.io/xmlrpc"> <link rel="webmention" href="https://webmention.io/oncletom.io/webmention"> <!-- Open Graph --> <meta property="og:type" content="book"> <meta property="og:image" content="https://oncletom.io/images/publications/nodejs-cover.png"> <meta property="og:book:author" content="Thomas Parisot"> <meta property="og:book:isbn" content="978-2212139938"> <meta property="og:book:release_date" content="2018-12-06"> <meta property="og:book:tag" content="Node.js"> <meta property="og:book:tag" content="JavaScript"> <meta property="og:book:tag" content="npm"> <meta property="og:book:tag" content="Développement front-end"> <meta property="og:book:tag" content="Développement back-end"> <meta property="og:locale" content="fr_FR"> <meta property="og:site_name" content="Node.js • Apprendre par la pratique"> <!-- Twitter OpenGraph --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@oncletom"> <meta name="twitter:creator" content="@oncletom"> <style type="text/css" class="extension-interactive-runner">[data-interactive-runtime="loaded"] .interactive--javascript code[data-lang]:before { background-color: #fcfcfc; border: 1px solid #0c2; border-radius: 1px; color: #0c2; cursor: pointer; display: inline-block; font-weight: bold; padding: .5em 1em; top: -2em; } [lang="en"] [data-interactive-runtime="loaded"] .interactive--javascript code[data-lang]:before { content: "▶ run code"; } [lang="fr"] [data-interactive-runtime="loaded"] .interactive--javascript code[data-lang]:before { content: "▶ voir le résultat"; } .interactive--javascript code[data-label]:before { content: attr(data-label); } .interactive iframe { position: absolute; visibility: hidden; } .interactive.status--loaded iframe { position: inherit; visibility: visible; } .interactive.status--loading { opacity: .5; } </style> <script class="extension-interactive-runner"> (function(d){ document.addEventListener('DOMContentLoaded', function(){ const script = d.createElement('script'); script.src = 'https://embed.runkit.com/'; script.async = true; script.onload = function(){ function makeListingInteractive (element){ if (element.classList.contains('interactive--installed') || element.classList.contains('status--loading')) { return; } const code = element.querySelector('code'); const nodeVersion = /interactive--runtime--node-([^\s]+)/.exec(element.className)[1]; const isEndpoint = element.classList.contains('interactive--endpoint'); const mode = isEndpoint ? 'endpoint' : null; let preamble = ''; const source = code .textContent .replace(/\/\/\s*\(\d+\)$/gm, '') .replace(/^["']?use strict["'][; ]*\n/, ''); if (isEndpoint) { preamble = `process.nextTick(() => { if (typeof module.exports === 'function') { exports.endpoint = module.exports; } else if (typeof server !== 'undefined') { exports.endpoint = server.listeners("request").pop(); } });` } element.classList.add('status--loading'); // eslint-disable-next-line no-undef RunKit.createNotebook({ nodeVersion, element, source, mode, preamble, onLoad: function(ntbk) { element.classList.add('interactive--installed'); element.classList.remove('status--loading'); element.classList.add('status--loaded'); code.parentNode.setAttribute('hidden', true); ntbk.evaluate(); } }); } function installEvents () { function getParent(el, condition) { let parent = el; while(parent = parent.parentNode) { if (condition(parent)) { return parent; } } } function hasClass(className) { return function check(el) { return el.classList.contains(className); } } document.querySelector('body').addEventListener('click', function(el) { if (el.target.classList.contains('language-javascript') || el.target.classList.contains('language-js')) { const parentNode = getParent( el.target, hasClass('interactive--javascript') ); makeListingInteractive(parentNode); } }); } installEvents(); document.body.dataset.interactiveRuntime = 'loaded'; }; document.body.appendChild(script); }); })(document);</script> <style type="text/css"> .listingblock [data-bash-subs]::before { content: attr(data-bash-subs) " "; opacity: .5; } .listingblock [data-bash-conum]::before { content: "(" attr(data-bash-conum) ")"; font-weight: bold; opacity: .7; }</style> <script> (function(d){ d.addEventListener('DOMContentLoaded', function(){ const {origin} = window.location; Array.from(document.querySelectorAll('a[href]')) .filter(link => link.href.indexOf(origin) !== 0) .forEach(link => { link.setAttribute('target', '_blank'); link.setAttribute('rel', 'noopener'); }); }); })(document);</script> <script> (function(d){ d.addEventListener('DOMContentLoaded', function(){ const script = d.createElement('script'); script.src = 'https://unpkg.com/menuspy@1.3.0/dist/menuspy.js'; script.async = true; script.onload = () => new MenuSpy(document.querySelector('#toc'), {enableLocationHash: false}); d.body.appendChild(script); }); })(document);</script> <style type="text/css"> #toc li.active > a[href^="#"] { font-weight: bold; } #toc li.active > a[href^="#"]::before { content: "▶ "; display: inline-block; position: absolute; margin-left: -1.2em; font-size: .8em; margin-top: 3px; } </style> </head> <body class="book toc2 toc-left"> <div id="header"> <h1>Jouer avec JavaScript</h1> <div id="toc" class="toc2"> <div id="toctitle">Table des matières</div> <ul class="sectlevel1"> <li><a href="#definition">1. Qu&#8217;est-ce que JavaScript ?</a> <ul class="sectlevel2"> <li><a href="#ecmascript5_aka_es5">1.1. ECMAScript&#160;5 (aka ES5)</a></li> <li><a href="#ecmascript_2015_akaes6_puises2015">1.2. ECMAScript 2015 (aka&#160;ES6 puis&#160;ES2015)</a></li> <li><a href="#ecmascript_2016_etc_akaes2016">1.3. ECMAScript 2016, etc. (aka&#160;ES2016)</a></li> </ul> </li> <li><a href="#primitives">2. Éléments de base du langage</a> <ul class="sectlevel2"> <li><a href="#les_types_de_données">2.1. Les types de données</a></li> <li><a href="#les_variables">2.2. Les variables</a></li> <li><a href="#les_instructions">2.3. Les instructions</a></li> <li><a href="#scope">2.4. La portée (scope)</a></li> </ul> </li> <li><a href="#string">3. Jongler avec du texte (chaînes de caractères)</a> <ul class="sectlevel2"> <li><a href="#regexp">3.1. Expressions régulières (RegExp)</a></li> </ul> </li> <li><a href="#boolean">4. Jongler avec des valeurs vraies ou fausses (booléens)</a></li> <li><a href="#number">5. Jongler avec des valeurs numériques (Number, Math)</a> <ul class="sectlevel2"> <li><a href="#opérations_mathématiques">5.1. Opérations mathématiques</a></li> <li><a href="#nan">5.2. Les nombres qui n&#8217;en sont pas (<em>NaN</em>)</a></li> <li><a href="#convertir_en_nombre">5.3. Convertir en nombre</a></li> <li><a href="#formater_et_arrondir_des_nombres">5.4. Formater et arrondir des nombres</a></li> </ul> </li> <li><a href="#functions">6. Créer et réutiliser des blocs de code (fonctions)</a> <ul class="sectlevel2"> <li><a href="#anonymous-function">6.1. Les fonctions anonymes</a></li> <li><a href="#callback">6.2. Les fonctions de rappel (callback)</a></li> <li><a href="#rest-parameters">6.3. Paramètres du reste (rest parameters)</a></li> </ul> </li> <li><a href="#array">7. Lister, filtrer et trier des éléments (Array)</a> <ul class="sectlevel2"> <li><a href="#créer_des_tableaux_à_partir_dautres_valeurs">7.1. Créer des tableaux à partir d&#8217;autres valeurs</a></li> <li><a href="#array.concat">7.2. Combiner des tableaux</a></li> <li><a href="#array.forEach">7.3. Itérer sur les valeurs avec des boucles</a></li> <li><a href="#array.sort">7.4. Trier les valeurs</a></li> <li><a href="#array.map">7.5. Transformer les valeurs</a></li> <li><a href="#array.filter">7.6. Filtrer les valeurs</a></li> <li><a href="#array.find">7.7. Identifier des valeurs</a></li> <li><a href="#array-destructuring">7.8. Décomposition de tableau (destructuring)</a></li> </ul> </li> <li><a href="#object">8. Représenter des structures d&#8217;objet et y accéder</a> <ul class="sectlevel2"> <li><a href="#object-destructuring">8.1. Décomposition d&#8217;objet (<em>destructuring</em>)</a></li> <li><a href="#object.assign">8.2. Combiner des objets</a></li> <li><a href="#itérer_sur_des_objets">8.3. Itérer sur des objets</a></li> <li><a href="#identifier_des_valeurs">8.4. Identifier des valeurs</a></li> </ul> </li> <li><a href="#json">9. Lire et écrire des données au format JSON</a></li> <li><a href="#date">10. Interagir avec des dates</a> <ul class="sectlevel2"> <li><a href="#intl.datetimeformat">10.1. Formatage internationalisé (Intl.DateTimeFormat)</a></li> </ul> </li> <li><a href="#class">11. Partager une logique avec des objets de même nature (Class)</a> <ul class="sectlevel2"> <li><a href="#class.method">11.1. Méthodes d&#8217;instance</a></li> <li><a href="#class.static">11.2. Méthodes statiques</a></li> <li><a href="#object-getset">11.3. Accesseurs et mutateurs</a></li> <li><a href="#class.extends">11.4. Héritage</a></li> </ul> </li> <li><a href="#promise">12. Coordonner des actions asynchrones (Promise)</a> <ul class="sectlevel2"> <li><a href="#promise.all">12.1. Collection de promesses</a></li> <li><a href="#async-await">12.2. async/await</a></li> </ul> </li> <li><a href="#conclusion">13. Conclusion</a></li> </ul> </div> </div> <div id="content"> <div id="preamble"> <div class="sectionbody"> <div class="admonitionblock tip context-callout"> <table> <tr> <td class="icon"> <div class="title">💡</div> </td> <td class="content"> <div class="paragraph"> <p>Vous êtes en train de lire le Chapitre 3 du <a href="https://oncletom.io/node.js/">livre &#8220;Node.js&#8221;</a>, écrit par <a href="https://oncletom.io">Thomas Parisot</a> et publié aux <a href="https://editions-eyrolles.com/Livre/9782212139938">Éditions Eyrolles</a>.</p> </div> <div class="paragraph"> <p>L&#8217;ouvrage vous plaît&#160;? Achetez-le sur <a href="https://amzn.to/2E58PEw">Amazon.fr</a> ou en <a href="https://www.placedeslibraires.fr/livre/9782212139938">librairie</a>. <a href="https://opencollective.com/nodebook">Donnez quelques euros</a> pour contribuer à sa gratuité en ligne.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>Passons en revue les variables et structures ECMAScript pour mieux comprendre ce qui en fait un langage élégant et moderne.</p> </div> <div class="exampleblock"> <div class="content"> <div class="ulist"> <div class="title">Sommaire</div> <ul> <li> <p>Qu&#8217;est-ce que JavaScript&#160;?</p> </li> <li> <p>Comprendre l&#8217;évolution de la spécification ECMAScript</p> </li> <li> <p>Jongler avec les différentes structures du langage</p> </li> <li> <p>En savoir plus sur des éléments avancés du langage</p> </li> </ul> </div> </div> </div> <div class="quoteblock abstract"> <blockquote> <div class="paragraph"> <p>JavaScript est souvent raillé. Parce que ce n&#8217;est pas un vrai langage. Parce qu&#8217;il a été créé en 6 jours. Parce qu&#8217;il n&#8217;est pas orienté objet.</p> </div> <div class="paragraph"> <p>JavaScript est un langage expressif qui a énormément gagné en maturité depuis les années 2010. Il se révèle parfaitement opérationnel dès lors que l&#8217;on s&#8217;intéresse à ses fonctionnalités, sans faire de hors-piste.</p> </div> <div class="paragraph"> <p>Les types de données et les méthodes de manipulations qu&#8217;elles nous offrent permettent d&#8217;écrire un code plus simple, à lire et à produire. Certaines structures de données nous aident à mieux organiser nos données ainsi qu&#8217;à mieux les traiter.</p> </div> </blockquote> </div> </div> </div> <div class="sect1"> <h2 id="definition">1. Qu&#8217;est-ce que JavaScript ?</h2> <div class="sectionbody"> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p>Je vais vous présenter plusieurs exemples de code. Ils ont en commun d&#8217;être tous écrits en JavaScript.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">intro/ecmascript.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> baseUrl <span class="token operator">=</span> <span class="token string">'https://oncletom.io/node.js'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> filePath <span class="token operator">=</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/package.json`</span></span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="paragraph"> <p>Cet exemple illustrait la création de variables, de chaînes de caractères. Ce sont des fonctionnalités de base de la spécification ECMAScript.</p> </div> <div class="listingblock"> <div class="title">intro/web.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">'https://oncletom.io/node.js/package.json'</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">pkg</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pkg<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">@</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pkg<span class="token punctuation">.</span>version<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="paragraph"> <p><code>fetch()</code> ne fait pas partie de la spécification ECMAScript. C&#8217;est un ajout des navigateurs web. On parle alors d'<strong>API JavaScript pour le Web</strong>.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">💬</div> </td> <td class="content"> <div class="title"><span class="RemarquePreTitre">Glossaire</span> API (Interface de programmation)</div> <div class="paragraph"> <p>Les API sont des interfaces pour dialoguer avec un programme ou une ressource informatique. Elles définissent des vocabulaires pour exécuter des actions spécifiques.</p> </div> </td> </tr> </table> </div> <div class="listingblock"> <div class="title">intro/dom.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> docBody <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> docBody<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'Hello World!'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="paragraph"> <p>La variable <code>document</code> et les méthodes <code>querySelector</code> et <code>addEventListener</code> font aussi partie des API JavaScript pour le Web. En l&#8217;occurrence, elles font partie de l&#8217;API DOM (<em>Document Object Model</em>), un mécanisme pour interagir avec une page web grâce à ECMAScript. </p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">intro/node.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span>homedir<span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'os'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> fs<span class="token punctuation">.</span><span class="token function">readdir</span><span class="token punctuation">(</span><span class="token function">homedir</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> files</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> err <span class="token operator">?</span> console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">:</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="paragraph"> <p>Ce dernier exemple est spécifique à Node. Ce dernier propose la fonction <code>require()</code> pour charger des modules et interagir avec le système d&#8217;exploitation. </p> </div> <div class="paragraph"> <p>Autrement dit, <strong>ECMAScript est un langage, une grammaire avec des fonctionnalités de base</strong>. Chaque environnement&#160;– les navigateurs web, Node&#160;– le comprend et lui ajoute de nouvelles expressions, contextuelles à cet environnement d&#8217;exécution. <strong>JavaScript est le grand ensemble des technologies qui reposent sur ECMAScript</strong> pour fonctionner.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">💬</div> </td> <td class="content"> <div class="title"><span class="RemarquePreTitre">Histoire</span> À propos de JavaScript</div> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p>JavaScript est inventé en 1995 par Brendan&#160;Eich alors qu&#8217;il est employé de la société Netscape Communications. Microsoft lui emboîte le pas en incluant JavaScript dans son logiciel Internet&#160;Explorer, alors en version&#160;3. Pour des raisons de droits de marque, il y est dénommé JScript.</p> </div> <div class="paragraph"> <p>La spécification est ensuite validée par l&#8217;organisme <em>Ecma International</em> en juin 1997 sous le nom d&#8217;ECMAScript, standard ECMA-262.</p> </div> <div class="paragraph"> <p>Le terme JavaScript est resté dans le vocabulaire courant, mais, en fait, il s&#8217;agit bien d&#8217;ECMAScript.</p> </div> <div class="paragraph"> <p>Adobe Flash utilise un dérivé d&#8217;ECMAScript&#160;: ActionScript. Bien des machines virtuelles sont capables d&#8217;interpréter partiellement ou intégralement ECMAScript&#160;: Rhino, Konq, BESEN en Object Pascal ou encore Esprima, qui est elle-même écrite dans ce langage.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>Si d&#8217;autres langages de programmation se cantonnent soit au côté client (VBScript, ActionScript, Elm), soit au côté serveur (Ruby, Python, Haskell), JavaScript a débuté côté client pour s&#8217;étendre aussi côté serveur. Un développeur ou une développeuse dite <em>full&#160;stack</em> programme des applications sur les deux fronts. Node a cet avantage d&#8217;unifier le langage de programmation entre les environnements client et serveur.</p> </div> <div class="paragraph"> <p>Le langage ECMAScript&#160;– appelons-le ainsi à partir de maintenant&#160;– a évolué au fil du temps. Il s&#8217;est enrichi de nouvelles fonctionnalités au fil des versions, mais aussi de sucres syntaxiques (raccourcis d&#8217;écriture) et de rigueur aussi, pour corriger des défauts de <em>design</em>.</p> </div> <div class="paragraph"> <p>Le comité de travail TC39 (<em>Technical Committee</em>, <span class="URL"><a href="https://github.com/tc39" class="bare">github.com/tc39</a></span>) est en charge de l&#8217;évolution du langage, standardisé sous le doux sobriquet de <em>standard ECMA-262</em>, à charge ensuite aux différents implémenteurs de suivre les changements et de les incorporer dans leurs machines virtuelles. </p> </div> <div class="paragraph"> <p>Node se base sur la machine virtuelle&#160;<a href="../chapter-01/index.html#v8">V8 de Google</a> pour interpréter les expressions ECMAScript. De fait, Node comprend les mêmes expressions ECMAScript que&#160;V8. </p> </div> <div class="paragraph"> <p>Nous verrons un peu plus tard dans ce chapitre comment suivre la compatibilité de Node avec ECMAScript. Intéressons-nous à l&#8217;évolution du langage et à ce que ça nous apporte.</p> </div> <div class="sect2"> <h3 id="ecmascript5_aka_es5">1.1. ECMAScript&#160;5 (aka ES5)</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p>ECMAScript a été standardisé dans sa version&#160;5 en décembre&#160;2009. La révision&#160;5.1 de juin&#160;2011 est une correction mineure de la spécification.</p> </div> <div class="paragraph"> <p>Il s&#8217;agit d&#8217;une évolution majeure dans l&#8217;histoire du langage. La précédente version&#160;– ECMAScript&#160;3&#160;– était âgée de dix&#160;ans.</p> </div> <div class="paragraph"> <p>ECMAScript&#160;5 limite drastiquement certains effets indésirables du langage grâce au <em>mode strict</em>. De nouvelles méthodes de manipulation de tableaux et d&#8217;objets voient le jour, ainsi qu&#8217;une prise en charge native du format de données&#160;<a href="#json">JSON</a>.</p> </div> <div class="paragraph"> <p>La standardisation de cette version d&#8217;ECMAScript a contribué à redorer l&#8217;image du langage, mais aussi à faire émerger de nouvelles pratiques de programmation.</p> </div> <div class="hdlist"> <table> <tr> <td class="hdlist1"> Table de compatibilité </td> <td class="hdlist2"> <p><span class="URL"><a href="https://kangax.github.io/compat-table/es5/" class="bare">kangax.github.io/compat-table/es5/</a></span></p> </td> </tr> <tr> <td class="hdlist1"> Spécification </td> <td class="hdlist2"> <p> <span class="URL"><a href="https://www.ecma-international.org/ecma-262/5.1/" class="bare">www.ecma-international.org/ecma-262/5.1/</a></span> </p> </td> </tr> </table> </div> <div class="imageblock"> <div class="content"> <img src="./images/compat-table.png" alt="compat table" width="85%"> </div> <div class="title">Figure 1. Table de compatibilité</div> </div> </div> <div class="sect2"> <h3 id="ecmascript_2015_akaes6_puises2015">1.2. ECMAScript 2015 (aka&#160;ES6 puis&#160;ES2015)</h3> <div class="paragraph"> <p> </p> </div> <div class="paragraph"> <p>La spécification ECMAScript&#160;2015 (ES2015) a été publiée en juin&#160;2015. Elle succède à ECMAScript&#160;5 après six années de gestation. Cette version a successivement été appelée ECMAScript Harmony, ECMAScript&#160;6, puis ECMAScript&#160;2015.</p> </div> <div class="paragraph"> <p>De nombreuses idées ont été piochées dans le langage CoffeeScript (<span class="URL"><a href="http://coffeescript.org" class="bare">coffeescript.org</a></span>). Et surtout, un nouveau type d&#8217;outillage s&#8217;est formé pour commencer à utiliser ce JavaScript du futur avec le compilateur <em>traceur</em> de Google dès&#160;2011 (<span class="URL"><a href="https://github.com/google/traceur-compiler" class="bare">github.com/google/traceur-compiler</a></span>), puis avec le projet indépendant <em>6to5</em> dès&#160;2014. Ce dernier a été renommé en Babel (<span class="URL"><a href="https://babeljs.io" class="bare">babeljs.io</a></span>) et son instigateur a par la suite été embauché par Facebook.</p> </div> <div class="paragraph"> <p>La pratique de compiler du JavaScript en JavaScript était en rupture avec ce qui se faisait précédemment&#160;: attendre qu&#8217;une fonctionnalité soit adoptée par un dénominateur commun de navigateurs web pour s&#8217;en servir. Cette fois-ci, on pouvait se servir du futur, dès aujourd&#8217;hui.</p> </div> <div class="paragraph"> <p>De fait, il n&#8217;y a pas eu à attendre six ans et les différentes implémentations pour profiter de ce qu&#8217;il y avait de meilleur.</p> </div> <div class="paragraph"> <p>Le prix à payer&#160;? Un ticket d&#8217;entrée plus élevé lié à la maîtrise de l&#8217;outillage associé.</p> </div> <div class="hdlist"> <table> <tr> <td class="hdlist1"> Table de compatibilité (navigateurs&#160;web) </td> <td class="hdlist2"> <p><span class="URL"><a href="https://kangax.github.io/compat-table/es6/" class="bare">kangax.github.io/compat-table/es6/</a></span></p> </td> </tr> <tr> <td class="hdlist1"> Table de compatibilité (Node.js) </td> <td class="hdlist2"> <p><span class="URL"><a href="https://node.green/" class="bare">node.green/</a></span></p> </td> </tr> <tr> <td class="hdlist1"> Spécification </td> <td class="hdlist2"> <p> <span class="URL"><a href="https://www.ecma-international.org/ecma-262/6.0/" class="bare">www.ecma-international.org/ecma-262/6.0/</a></span> </p> </td> </tr> </table> </div> <div class="imageblock"> <div class="content"> <img src="./images/node-green.png" alt="node green" width="85%"> </div> <div class="title">Figure 2. Illustration de l&#8217;évolution de la compatibilité ECMAScript au fil des versions de&#160;Node</div> </div> </div> <div class="sect2"> <h3 id="ecmascript_2016_etc_akaes2016">1.3. ECMAScript 2016, etc. (aka&#160;ES2016)</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p>Depuis la sortie d&#8217;ECMAScript&#160;2015, l&#8217;intention est de publier une nouvelle spécification par an, de travailler les fonctionnalités une par une pour ne pas attendre trop longtemps avant de les ratifier. En conséquence, les nouvelles versions annuelles sont beaucoup plus incrémentales. Elles se font moins attendre et contiennent moins de grands bouleversements.</p> </div> <div class="paragraph"> <p>Les fonctionnalités en cours de préparation sont listées dans le dépôt GitHub suivant&#160;: <span class="URL"><a href="https://github.com/tc39/proposals" class="bare">github.com/tc39/proposals</a></span>. Le dernier stade avant la validation est le <em>stage&#160;3</em>. Dès qu&#8217;une fonctionnalité passe en <em>stage&#160;4</em>, elle est incluse dans la prochaine version d&#8217;ECMAScript – ECMAScript&#160;2019 une fois l&#8217;année 2019 terminée.</p> </div> <div class="paragraph"> <p>Les fonctionnalités approuvées sont consignées dans un document&#160;: <span class="URL"><a href="https://github.com/tc39/proposals/blob/master/finished-proposals.md" class="bare">github.com/tc39/proposals/blob/master/finished-proposals.md</a></span>.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="primitives">2. Éléments de base du langage</h2> <div class="sectionbody"> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p>Cette section décrit les notions nécessaires pour s&#8217;approprier le reste des exemples de l&#8217;ouvrage. On apprendra notamment à créer des variables, à naviguer dans des listes d&#8217;éléments et à faire la différence entre un objet et une fonction.</p> </div> <div class="sect2"> <h3 id="les_types_de_données">2.1. Les types de données</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p>Qu&#8217;entend-on par <em>type de données</em>&#160;? Faisons-nous notre propre idée avec une suite d&#8217;exemples. Ces notions seront développées dans le reste du chapitre, pour mieux comprendre ce que l&#8217;on peut en faire.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/string.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token string">'Node.js'</span></code></pre> </div> </div> <div class="paragraph"> <p>Une valeur entourée de guillemets est considérée par l&#8217;interpréteur ECMAScript comme une chaîne de caractères, du texte. </p> </div> <div class="paragraph"> <p>Ces guillemets sont selon les cas des guillemets simples&#160;('), doubles (") ou obliques (`).</p> </div> <div class="paragraph"> <p>On peut effectuer des opérations d&#8217;identification ou d&#8217;assemblage avec une valeur de type <strong>chaîne de caractères</strong>.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/number.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token number">3</span> <span class="token number">12.3</span></code></pre> </div> </div> <div class="paragraph"> <p>ECMAScript considère les entiers (<code>3</code>&#160;dans cet exemple) et les réels (<code>12.3</code>&#160;dans cet exemple) comme des nombres. Il ne fait <em>pas</em> de distinction entre les&#160;deux. </p> </div> <div class="paragraph"> <p>On peut effectuer des opérations mathématiques entre plusieurs valeurs de type <strong>nombre</strong>.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/boolean.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token boolean">true</span> <span class="token boolean">false</span></code></pre> </div> </div> <div class="paragraph"> <p>ECMAScript considère deux valeurs pour signifier <em>vrai</em> ou <em>faux</em>&#160;: respectivement <code>true</code> et <code>false</code>. </p> </div> <div class="paragraph"> <p>On peut effectuer des opérations logiques avec une valeur de type <strong>booléen</strong>.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/null.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token keyword">null</span></code></pre> </div> </div> <div class="paragraph"> <p>On utilise <code>null</code> pour signifier l'<strong>absence de valeur</strong>.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/undefined.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token keyword">undefined</span></code></pre> </div> </div> <div class="paragraph"> <p>La valeur <code>undefined</code> est utilisée pour signifier qu&#8217;une <strong>valeur</strong> est <strong>inconnue</strong>. Rares sont les cas où on choisira ce type de données par nous-même. </p> </div> <div class="admonitionblock note info"> <table> <tr> <td class="icon"> <div class="title">📖</div> </td> <td class="content"> <div class="title"><span class="RemarquePreTitre">Documentation</span> Primitives</div> Rendez-vous sur <em>MDN web docs</em> pour en savoir plus sur primitives.<br> <a href="https://developer.mozilla.org/docs/fr/Web/JavaScript/Data_structures" class="bare URL" target="_blank" rel="noopener">developer.mozilla.org/docs/fr/Web/JavaScript/Data_structures</a> </td> </tr> </table> </div> <div class="paragraph"> <p>Il existe trois autres types de données qui se basent sur ces types dits <em>primitifs</em>. Ils sont destinés à ranger, à classer et à exprimer de nouvelles valeurs en fonction d&#8217;autres.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/array.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'C'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'G'</span><span class="token punctuation">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Un tableau se déclare en encadrant une suite de valeurs entre crochets. Il est capable de contenir n&#8217;importe quel type de valeurs et autant que nécessaire. L&#8217;ordre des valeurs a généralement une importance. </p> </div> <div class="paragraph"> <p>On peut effectuer des opérations de tri et de sélection avec un <strong>tableau de valeurs</strong>.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/object.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token punctuation">{</span> title<span class="token punctuation">:</span> <span class="token string">'Node.js'</span><span class="token punctuation">,</span> isbn<span class="token punctuation">:</span> <span class="token string">'978-2212139938'</span><span class="token punctuation">,</span> published<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Un objet se déclare en encadrant une suite de <em>paires clé/valeur</em> entre accolades. Il fonctionne comme un <em>dictionnaire</em>&#160;: on associe une valeur (type au choix) à une clé (un intitulé, un label). L&#8217;ordre des paires n&#8217;a généralement pas d&#8217;importance. </p> </div> <div class="paragraph"> <p>On peut effectuer des opérations de sélection avec un <strong>objet de valeurs</strong>.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/function.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token keyword">function</span> <span class="token function">double</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> value <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">double</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="paragraph"> <p>Une fonction accepte des <em>arguments</em>, de n&#8217;importe quel type et autant que nécessaire. Elle doit être <em>déclarée</em> pour être <em>exécutée</em> (dernière ligne de l&#8217;exemple précédent). </p> </div> <div class="paragraph"> <p>Une fonction <em>retourne</em> un résultat explicite avec le mot-clé <code>return</code>. Dans le cas contraire, ECMAScript considère que la valeur retournée équivaut implicitement à <code>undefined</code>.</p> </div> <div class="paragraph"> <p>On peut effectuer des opérations de transformation avec une fonction.</p> </div> <div class="paragraph"> <p>Les fonctions sont destinées à être <em>appelées</em>, pour effectuer des traitements répétitifs. Dès que l&#8217;on doit écrire deux fois la même chose, on l&#8217;écrit dans une fonction qu&#8217;on appelle deux&#160;fois.</p> </div> </div> <div class="sect2"> <h3 id="les_variables">2.2. Les variables</h3> <div class="paragraph"> <p></p> </div> <div class="paragraph"> <p>Les variables servent à ranger des valeurs. On peut ainsi les réutiliser plus tard, les transmettre et prendre des décisions en fonction de ce qu&#8217;elles contiennent.</p> </div> <div class="paragraph"> <p>Les variables nous aident à <em>donner du sens</em> à notre code, à le rendre intelligible par d&#8217;autres personnes ainsi qu&#8217;à nommer des choses comme on le ferait dans notre quotidien.</p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">base/variables.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token keyword">const</span> book <span class="token operator">=</span> <span class="token punctuation">{</span> title<span class="token punctuation">:</span> <span class="token string">'Node.js'</span><span class="token punctuation">,</span> isbn<span class="token punctuation">:</span> <span class="token string">'978-2212139938'</span><span class="token punctuation">,</span> published<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> base_price <span class="token operator">=</span> <span class="token number">13</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">double</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> value <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> book<span class="token punctuation">.</span>price <span class="token operator">=</span> <span class="token function">double</span><span class="token punctuation">(</span>base_price<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="paragraph"> <p>À votre avis, quel est le prix du livre calculé dans l&#8217;exemple précédent&#160;? Il suffit de suivre le chemin que prend la nouvelle valeur rangée dans la clé <code>price</code> de l&#8217;objet <code>book</code>, calculée par la fonction <code>double</code> à laquelle on passe la valeur contenue dans la variable <code>base_price</code>.</p> </div> <div class="paragraph"> <p>Le mot-clé <code>const</code> nous a servi à <em>déclarer</em> une variable. On ne peut étiqueter ainsi une variable avec le même nom qu&#8217;une seule fois. L&#8217;exemple suivant générera une erreur lors de la deuxième affectation&#160;: </p> </div> <div class="listingblock interactive interactive--javascript interactive--runtime--node-v10"> <div class="title">variables/const.js</div> <div class="content"> <pre class="highlight highlight-prismjs prismjs language-javascript"><code class="language-javascript" data-lang="javascript"><span class="token keyword">const</span> base_price <span class="token operator">=</span> <span class="token number">13</span><span class="token punctuation">;</span> <span class="token keyword">const</span> base_price <span class="token operator">=</span> <span class="token number">14</span><span class="token punctuation">;</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">💬</div> </td> <td class="content"> <div class="title"><span class="RemarquePreTitre">Question