<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[JS Attitude]]></title>
  <link href="http://www.js-attitude.fr/atom.xml" rel="self"/>
  <link href="http://www.js-attitude.fr/"/>
  <updated>2013-05-21T14:32:46+02:00</updated>
  <id>http://www.js-attitude.fr/</id>
  <author>
    <name><![CDATA[Christophe Porteneuve &amp; Delicious Insights]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Internationaliser son JavaScript]]></title>
    <link href="http://www.js-attitude.fr/2013/05/21/internationaliser-son-javascript/"/>
    <updated>2013-05-21T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2013/05/21/internationaliser-son-javascript</id>
    <content type="html"><![CDATA[<p><img class="right" src="http://sudweb.fr/2013/img/logo.png" width="249" height="200" title="logo de Sud Web 2013" ></p>

<p>J&#8217;ai récemment eu le plaisir d&#8217;être orateur à <a href="http://sudweb.fr/2013/">Sud Web 2013</a>, au titre d&#8217;un élaboratoire intitulé <a href="http://delicious-insights.com/g11n-js/">Internationaliser son JavaScript</a>, un sujet qui me tient à cœur mais qui est hélas très peu traité pour le moment.</p>

<p>Déjà que les développeurs prennent rarement soin d&#8217;internationaliser (correctement) leurs sites web côté back, mais alors côté front, c&#8217;est un véritable désert…  Même les « gros du Web », tels que Google, PayPal, e-Bay, Twitter, Facebook et consorts font montre d&#8217;un certain laxisme (voire d&#8217;un laxisme certain) sur ces sujets.</p>

<p>La première étape, c&#8217;est d&#8217;admettre qu&#8217;il y a un problème, comme disait l&#8217;autre.  À partir de quoi, il faut savoir que nombre d&#8217;outils et de technos existent, et qu&#8217;avec un peu de professionnalisme et de bonnes pratiques on peut fournir une expérience parfaitement <em>globalisée</em> sur de multiples <em>locales</em> (contextes culturels et linguistiques).</p>

<p>Sensibiliser au problème et faire le tour de la question était tout l&#8217;objet de cet élaboratoire, dont <a href="http://delicious-insights.com/g11n-js/">les slides sont consultables en ligne</a>.</p>

<p><em>Enjoy!</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Formations Attitude : un premier bilan]]></title>
    <link href="http://www.js-attitude.fr/2013/04/22/attitude-un-premier-bilan/"/>
    <updated>2013-04-22T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2013/04/22/attitude-un-premier-bilan</id>
    <content type="html"><![CDATA[<p>Pour un organisme de formation, le mois d&#8217;avril est l&#8217;échéance de dépôt du <em>Bilan Pédagogique et Financier</em> (BPF), pour lequel nous devons compulser toutes sortes de statistiques et compteurs sur nos stagiaires, sessions, heures de formations, origines des règlements, etc.  C&#8217;est aussi amusant que de lire du COBOL à jeun.</p>

<p>Ceci étant dit, c&#8217;est l&#8217;occasion de faire le point sur l&#8217;évolution de notre activité de formation.  Et comme Attitude, c&#8217;est avant tout la transparence, je me suis dit que ça pourrait vous intéresser de voir d&#8217;où nous sommes partis et où nous en sommes.</p>

<p><em>(note : cet article est posté sur l&#8217;ensemble des sites Attitude)</em></p>

<!-- more -->


<h2>Pratiquement 3 ans</h2>

<p>Si Delicious Insights n&#8217;existe que depuis août 2011, notre activité de formation a démarré bien avant cela, sous d&#8217;autres formes : dès le 2 juillet 2010, pour être précis.  C&#8217;était la première formation <a href="http://www.git-attitude.fr/git-au-quotidien/">Git au Quotidien</a>, déjà chez Clever Age et à un tarif ubuesque pour les valeureux pionniers qui osaient l&#8217;aventure : 50€ la journée, déjeuner compris !</p>

<p>Lorsqu&#8217;en octobre j&#8217;expliquais l&#8217;idée derrière <a href="http://www.git-attitude.fr/">Git Attitude</a> aux copains pendant <a href="http://www.paris-web.fr/">Paris Web</a>, ce bon vieux <a href="http://jeremie.patonnier.net/">Jérémie Patonnier</a> m&#8217;a dit sur un ton débonnaire et détaché : « mais pourquoi tu ne fais pas la même chose avec JavaScript ? ». Après m&#8217;être tapé la tête contre le mur de ne pas y avoir pensé dès le début, j&#8217;ai donc lancé <a href="http://www.js-attitude.fr/">JS Attitude</a> avec tout d&#8217;abord <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> et une première session bondée (16 personnes !) le 27 novembre, vendue en quelques jours, presque quelques heures…</p>

<p>Voici un petit historique de jalons sélectionnés :</p>

<table>
<thead>
<tr>
<th>Date             </th>
<th> Jalon</th>
</tr>
</thead>
<tbody>
<tr>
<td>2 juillet 2010   </td>
<td> Lancement Git Attitude (Git Quotidien)</td>
</tr>
<tr>
<td>27 novembre 2011 </td>
<td> Lancement JS Attitude (JS Puissant)</td>
</tr>
<tr>
<td>19 février 2011  </td>
<td> Premier <a href="http://www.git-attitude.fr/git-avance/">Git Avancé</a></td>
</tr>
<tr>
<td>12 mars 2011     </td>
<td> <a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> v1</td>
</tr>
<tr>
<td>mai 2011         </td>
<td> Premières sessions intra-entreprises (Blablacar / Comuto, Intel)</td>
</tr>
<tr>
<td>2 juillet 2011   </td>
<td> JS Guru v2</td>
</tr>
<tr>
<td><strong>26 août 2011</strong> </td>
<td> <strong>Immatriculation de Delicious Insights</strong></td>
</tr>
<tr>
<td>25 février 2012  </td>
<td> JS Guru v3</td>
</tr>
<tr>
<td>août 2012        </td>
<td> Nouvelle tarification (dont tarifs fidélité), passage des inter à <a href="http://www.js-attitude.fr/informations-generales/#le-lieu%20de%20formation">l&#8217;Espace La Rochefoucauld</a></td>
</tr>
<tr>
<td>septembre 2012   </td>
<td> Création du blockbuster <a href="http://www.js-attitude.fr/js-total/">JS Total</a> pour Digitas / Vivaki</td>
</tr>
<tr>
<td>décembre 2012    </td>
<td> Création de la formation <a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a></td>
</tr>
<tr>
<td>15 novembre 2012 </td>
<td> Je passe à temps plein sur Delicious Insights</td>
</tr>
<tr>
<td>23 novembre 2012 </td>
<td> Première formation en anglais (Kelkoo)</td>
</tr>
<tr>
<td>mars 2013        </td>
<td> Premières formations intra à l&#8217;étranger (Bruxelles)</td>
</tr>
</tbody>
</table>


<h2>Quelques chiffres</h2>

<p>Je vous passe l&#8217;évolution d&#8217;un exercice fiscal à l&#8217;autre, mais sachez qu&#8217;aujourd&#8217;hui, Delicious Insights, au travers de Git Attitude et JS Attitude, c&#8217;est :</p>

<ul>
<li><strong>7 formations</strong> au catalogue (3 Git et 4 JavaScript)</li>
<li><strong>52 sessions</strong> déjà données, soit</li>
<li><strong>544 heures</strong> de formation à destination de</li>
<li><strong>444 stagiaires</strong> au sein de</li>
<li>plus de <strong>80 sociétés</strong> clientes (et de nombreux participants à titre personnel)</li>
</ul>


<p>Parmi nos clients, un équilibre surprenant entre TPE/PME, agences (TBWA, MRM Worldwide, Fullsix / Ekino…), SSII (Atos, Valtech…) et grands comptes (SNCF, Orange, EADS, Dassault, Intel, Alcatel-Lucent, 4D, FNAC, l’OCDE, Météo France, MisterGoodDeal, PriceMinister…).  Des clients situés dans 5 pays : France, Royaume-Uni, Belgique, Suisse et Luxembourg.</p>

<h2>Des stagiaires enchantés</h2>

<p>Tous nos stagiaires ont l&#8217;occasion de faire un retour à chaud en fin de session, face à face, ainsi qu&#8217;un retour à froid <em>via</em> un formulaire en ligne proposant des évaluations tant quantitatives (notes de 1 à 5) que qualitatives (texte libre).  Un bon tiers de nos stagiaires prennent le temps de le remplir (une proportion historique qui, toutefois, ne cesse de s&#8217;améliorer).  Nous n&#8217;avons rien à cacher, alors allez donc consulter un <a href="http://whygit.wufoo.com/reports/evaluation-des-ateliers-attitude/">rapport temps réel sur les retours qui nous sont faits</a>.</p>

<h2>Merci à vous</h2>

<p>Je voudrais profiter de cet article pour <strong>remercier très chaleureusement tous les stagiaires</strong> qui nous ont fait confiance jusqu&#8217;ici, et leurs employeurs qui ont accepté de les envoyer dans nos formations.  C&#8217;est un plaisir chaque fois renouvellé de vous transmettre tout ce qu&#8217;on peut, d&#8217;échanger avec vous et de lire vos retours !</p>

<h2>Et maintenant ?</h2>

<p>Eh bien, on va commencer par finir l&#8217;exercice en cours (au 30 juin), et préparer la rentrée…</p>

<p>Je souhaite rédiger <strong>davantage d&#8217;articles de fond</strong>, ainsi que de la retranscription de veille et des didacticiels sur diverses technos, sur les différents sites Attitude.</p>

<p>J&#8217;ai très envie de pouvoir mettre au catalogue des <strong>formations Node.js, Ruby et Rails</strong>, mais on verra si le temps de préparation ne fait pas trop défaut.</p>

<p>On va probablement élargir petit à petit le groupe de formateurs, aussi, en travaillant avec des personnes de confiance qu&#8217;on connaît de longue date, qui partagent notre philosophie, nos valeurs, et font preuve d&#8217;une expertise technique et d&#8217;une pédagogie à la hauteur de nos exigences.</p>

<p>Enfin, le catalogue de formations va faire l&#8217;objet au fur et à mesure d&#8217;une déclinaison sous forme de <strong>screencasts qualitatifs payants</strong>, d&#8217;une heure environ chacun, avec des possibilités d&#8217;achat par lot (pour toute la série &#8220;Git au Quotidien&#8221; par exemple), les stagiaires bénéficiant automatiquement d&#8217;un fort rabais sur ces derniers.</p>

<p>Espérons qu&#8217;on aura le temps de tout faire !</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Plus de place à JS Total ? Venez à JS Puissant et JS Guru !]]></title>
    <link href="http://www.js-attitude.fr/2013/04/19/alternative-a-js-total/"/>
    <updated>2013-04-19T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2013/04/19/alternative-a-js-total</id>
    <content type="html"><![CDATA[<p>La dernière session <a href="http://www.js-attitude.fr/js-total/">JS Total</a> inter-entreprises avant la rentrée, qui est planifiée du 25 au 28 juin, est complète depuis quelques jours.  Nous recevons quelques demandes frustrées de n&#8217;avoir pas pu s&#8217;inscrire assez tôt.  Il est vrai que JS Total, qui est un peu « le Disneyland de la formation JavaScript », est quelque peu victime de son succès.</p>

<p>Si vous avez suffisamment de personnes demandeuses dans votre entreprise, vous pouvez nous contacter pour une <a href="http://www.js-attitude.fr/demander-une-intra-ou-custom/">JS Total en intra-entreprise</a> ; on n&#8217;a plus de place sur mai et juin mais si vous le souhaitez, on peut faire ça en juillet ou août (au mépris de la sacro-sainte stupeur-tout-l&#8217;été si française).</p>

<p>Dans le cas contraire, je ne saurais trop vous encourager à prendre la meilleure option restante : une <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> suivie d&#8217;une <a href="http://www.js-attitude.fr/js-guru/">JS Guru</a>.  Ces deux sessions correspondent à peu près aux journées 1 et 3 de JS Total, et sont donc <strong>très intéressantes</strong>.  Qui plus est, vous aurez le temps de « digérer » JS Puissant pendant 3 semaines avant d&#8217;attaquer JS Guru.</p>

<p>Chacune n&#8217;a en effet plus qu&#8217;une date avant l&#8217;été :</p>

<ul>
<li>JS Puissant <strong>mardi 30 avril 2013</strong> (c&#8217;est très bientôt !)</li>
<li>JS Guru <strong>mardi 21 mai 2013</strong> (non, cette semaine-là ne contient pas de pont, on a vérifié…)</li>
</ul>


<p>La session du 30 avril manque actuellement d&#8217;une personne pour atteindre son quorum minimal de participants, je vous invite donc à <a href="http://www.js-attitude.fr/demander-une-convention/">faire établir votre convention</a> au grand plus tard <strong>mardi 23</strong>, histoire de garantir la date !</p>

<p>Parmi les retours en ligne effectués sur ces formations, on trouve par exemple :</p>

<blockquote><p>Waouh ! Cool ! C’était trop bien :-) … et merci ! Merci beaucoup de partager ainsi toute cette connaissance. On a juste envie en sortant de là, de s’y mettre à fond, d&#8217;approfondir encore plus les choses et de ne plus pratiquer que le JS !  C’était passionnant !</p><footer><strong>Christelle P.</strong> <cite>01/03/2013</cite></footer></blockquote>




<blockquote><p>Vraiment très bien. Je vois javascript différemment maintenant. Il s&#8217;agit d&#8217;un langage puissant quand on l&#8217;utilise bien.</p><footer><strong>Jonathan P.</strong> <cite>19/02/2013</cite></footer></blockquote>




<blockquote><p>La meilleure formation [que j’aie] jamais faite, toutes technos confondues !  À recommander à toute personne désirant s&#8217;améliorer en JS.</p><footer><strong>Loïc M.</strong> <cite>11/02/2013</cite></footer></blockquote>




<blockquote><p>Super formateur qui m&#8217;a boosté pour les 100 prochaines années, super passionné !!  Que du +++</p><footer><strong>Charles B.</strong> <cite>11/02/2013</cite></footer></blockquote>




<blockquote><p>Je trouve que cette formation était excellente de bout en bout. […] Merci à toi Christophe pour cette formation dynamique et passionnante !</p><footer><strong>Matthieu C.</strong> <cite>17/12/2013</cite></footer></blockquote>


<p>Et encore, on en passe plein…</p>

<p><a href="http://www.js-attitude.fr/demander-une-convention/">Dépêchez-vous !</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Pourquoi une formation CoffeeScript ?]]></title>
    <link href="http://www.js-attitude.fr/2013/04/02/pourquoi-une-formation-coffeescript/"/>
    <updated>2013-04-02T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2013/04/02/pourquoi-une-formation-coffeescript</id>
    <content type="html"><![CDATA[<p>Les sessions de <a href="http://www.js-attitude.fr/coffee-script/">formation CoffeeScript</a>, aussi <strong>étourdissantes</strong> et <strong>excitantes</strong> soient-elles, ne rencontrent pas (encore) le succès escompté.  Les quelques-uns qui sont assez visionnaires/innovants/audacieux/malins pour s&#8217;y inscrire se voient hélas reportés de date en date, jusqu&#8217;à atteindre le <em>quorum</em> minimum de 4 personnes pour une session.</p>

<p>C&#8217;est assez navrant, mais pas vraiment surprenant, vu les travers habituels du secteur des « nouvelles technologies » en France, lequel—à l&#8217;exception de trop peu d’individus aussi brillants que passionnés, dont vous êtes certainement—a toujours marqué une ironique aversion envers tout ce qui est effectivement nouveau.</p>

<p>Laissez-moi donc vous expliquer brièvement <strong>pourquoi CoffeeScript est important</strong>, et pourquoi <strong>votre avenir passe par lui</strong> ou, tout du moins, s&#8217;en inspire.</p>

<!-- more -->


<h2>CoffeeScript, qu&#8217;est-ce que c&#8217;est exactement ?</h2>

<p>CoffeeScript est « le petit langage qui compile vers JavaScript ».  Il s&#8217;agit d&#8217;un langage de plus haut niveau, créé et principalement maintenu par l&#8217;excellent Jérémy Ashkenas (qui nous a aussi donnés, entre autres, <a href="http://backbonejs.org/">Backbone</a> et <a href="http://underscorejs.org/">Underscore</a> ; ça se pose là, comme historique…).</p>

<p>Alors que chaque jour JavaScript devient un peu plus une machine virtuelle (VM) pour le web, dont les performances s&#8217;approchent <a href="http://blog.mozilla.org/blog/2013/03/27/mozilla-is-unlocking-the-power-of-the-web-as-a-platform-for-gaming/">de plus en plus vite</a> du natif (et parfois même le dépassent), les langages qui « compilent vers JavaScript » sont de plus en plus nombreux, comme en témoigne <a href="http://altjs.org/">AltJS</a>.</p>

<p>CoffeeScript est de loin <strong>le plus populaire</strong> : alors que JavaScript est le langage n°1 sur Github (21% des projets à l&#8217;heure ou j&#8217;écris ceci), CoffeeScript <a href="https://github.com/languages/CoffeeScript">est déjà 11ème</a>, en passe de dépasser Objective-C (le langage de programmation de OSX et iOS). Chaque jour, davantage de bibliothèques (ex. <a href="http://underscorejs.org/">Underscore</a>), frameworks (ex. <a href="http://batmanjs.org/">BatmanJS</a>), modules Node et outils (ex. <a href="http://pow.cx/">Pow</a>) passent leur code source en CoffeeScript, en maintienant une distribution JavaScript disponible.</p>

<p>CoffeeScript n&#8217;est pas là pour <em>remplacer</em> JavaScript : il est là pour <strong>l&#8217;améliorer</strong> et expérimenter avec des nouvelles syntaxes, approches et fonctionnalités.  Il est là pour <strong>montrer la voie</strong>, et réussit admirablement, comme en témoigne l&#8217;inspiration forte que lui reconnaît explicitement ES6 (ES.Next / Harmony : la prochaine version de JavaScript).</p>

<p>En attendant, CoffeeScript produit du JavaScript <strong>compatible avec tous les navigateurs</strong> (même IE6, oui oui) et moteurs, à savoir du ES3 / JS 1.5.  Au final, c&#8217;est juste du JavaScript.  Mais plus rapide, plus performant, plus efficace, plus <em>qualitatif</em> que le vôtre.  Et quand bien même vous seriez un JavaScripter de génie, faire la même chose en CoffeeScript <em>va plus vite</em> et est <em>plus agréable</em>.</p>

<h2>Pour les débutants comme pour les chevronnés</h2>

<p>Contrairement à d&#8217;autres technologies ou langages « AltJS », CoffeeScript ne cherche pas à vous éloigner de JavaScript.  Les concepts-clés de ce dernier, comme le <em>binding</em>, les <em>closures</em>, les prototypes, les règles de portée, etc. ont toujours toute leur place.</p>

<p>CoffeeScript est là pour fournir une manière <strong>plus concise, plus lisible, plus performante</strong> d&#8217;écrire la plupart des idiômes de JavaScript, qu&#8217;ils soient simples ou avancés.</p>

<p>Même un développeur JavaScript chevronné court le risque d&#8217;un moment d&#8217;inattention lorsqu&#8217;il réalise un héritage prototypal, manipule le <em>binding</em> explicitement ou copie-colle des composants de tableau ; il pestera tout autant qu&#8217;un débutant devant la quantité de code (et donc de source potentielle de bugs) nécessaire au <em>resting/spreading</em> d&#8217;arguments, à une itération filtrée, ou même à une simple boucle numérique.</p>

<p>Ce n&#8217;est pas par hasard qu&#8217;on trouve parmi les défendeurs de CoffeeScript des grands noms de JavaScript, à commencer par <strong>Brendan Eich</strong> lui-même, CTO de Mozilla, inventeur et mainteneur en chef de JavaScript !</p>

<h2>JavaScript, sans le bruit</h2>

<p>La première chose qu&#8217;on remarque quand on se met à CoffeeScript, c&#8217;est la <strong>réduction du bruit syntaxique</strong>.</p>

<p>L&#8217;indentation étant significative (comme en Python, HAML, Jade, Makefile et bien d&#8217;autres), il n&#8217;y a plus besoin d&#8217;accolades.  En améliorant également le <em>parser</em> (l&#8217;analyseur syntaxique), on peut se passer de nombreux délimiteurs et séparateurs, autoriser davantage de syntaxes multi-lignes, et permettre divers petites astuces de confort.  En voici quelques-unes :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="c1"># La dernière virgule ne gêne pas : couper-coller facilité !</span>
</span><span class='line'><span class="nv">names = </span><span class="p">[</span>
</span><span class='line'>  <span class="s">&#39;Élodie&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&#39;Alexis&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&#39;Rudy&#39;</span><span class="p">,</span>
</span><span class='line'><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Litéraux objets simplifiés</span>
</span><span class='line'><span class="nv">author =</span>
</span><span class='line'>  <span class="nv">name: </span><span class="s">&#39;Christophe&#39;</span>
</span><span class='line'>  <span class="nv">age: </span><span class="mi">35</span>
</span><span class='line'>  <span class="nv">city: </span><span class="s">&#39;Paris&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Expressions de fonctions et interpolation de chaînes</span>
</span><span class='line'><span class="nv">sayHi = </span><span class="nf">(whom) -&gt;</span> <span class="s">&quot;Salut </span><span class="si">#{</span><span class="nx">whom</span><span class="si">}</span><span class="s"> !&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>JavaScript, sans les pièges</h2>

<p>JavaScript a bien quelques verrues, dues à la fenêtre de temps extrêmement courte (10 jours) de sa conception initiale.  Parmi celles-ci, on compte notamment les variables globales par défaut, les protocoles de conversion implicite, la perte du <em>binding</em> sur les références de fonction et la copie <em>verbatim</em> de l&#8217;API <code>Date</code> de Java.</p>

<p>CoffeeScript prend soin de <strong>vous protéger autant que possible</strong> de ces écueils.</p>

<p>Par exemple, toutes les variables employées sont <strong>automatiquement locales</strong> (déclarées <code>var</code>), sauf à ce qu&#8217;elles figurent aussi sur une portée englobante, auquel cas on suppose une identité (pas de masquage local).  Puisque tout fichier CoffeeScript est <strong>traité comme un module</strong> (englobé dans un <em>module pattern</em>), la pollution de l&#8217;espace de noms global ne peut plus être qu&#8217;intentionnelle (et honteuse).</p>

<p>Les comparaisons laxistes <code>==</code> et <code>!=</code> sont traduites en versions strictes <code>===</code> et <code>!==</code> en JavaScript ; d&#8217;ailleurs, les opérateurs <code>==</code> et <code>!=</code> sont découragés au profit de <code>is</code> et <code>isnt</code>, plus lisibles et moins porteurs d&#8217;une mauvaise interprétation.  La conversion de type se doit donc d&#8217;être explicite, ce qui est une bonne pratique.</p>

<p>La boucle <code>for…in</code> étant utilisée sur des tableaux (à tort) par tous les débutants JS, en particuliers ceux habitués à PHP, CoffeeScript en fait une vraie boucle (numérique) sur tableaux et utilise <code>for…of</code> pour itérer sur les propriétés d&#8217;un objet.</p>

<p>Il est possible de forcer le <em>binding</em> d&#8217;une méthode, ou d&#8217;une fonction anonyme de callback, rien qu&#8217;en remplaçant la flèche simple <code>-&gt;</code> par une double <code>=&gt;</code> (<em>fat arrow</em>).</p>

<p>Et j&#8217;en passe…</p>

<h2>JavaScript, plus qualitatif et plus performant</h2>

<p>L&#8217;étude du <strong>code JS généré</strong> par CoffeeScript est <strong>riche d&#8217;enseignements</strong>.  L&#8217;opération étant volontairement <strong>transparente</strong> (elle prend soin de faciliter la mise en correspondance mentale entre code CoffeeScript et code JavaScript), on peut y repérer une grande quantité de bonnes pratiques et d&#8217;optimisations qui font tristement défaut à la grande majorité des codes écrits manuellement.</p>

<p>Du <em>hoisting</em> explicite des variables à <strong>l&#8217;optimisation des boucles</strong> sur tableaux en passant par le recours systématique et optimal à <code>slice</code> et <code>splice</code>, il est rapidement manifeste que le code généré par CoffeeScript est <strong>plus qualitatif et dans l&#8217;ensemble plus performant</strong> que celui écrit à la main, même par un expert.  De la même façon, finalement, que le code produit par un compilateur surclassera généralement le code assembleur écrit à la main par un humain (et le code de plus haut niveau aura pris une fraction du temps à écrire).</p>

<h2>Des syntaxes complémentaires super utiles</h2>

<p>CoffeeScript regorge de syntaxes concises, le plus souvent très lisibles (plus lisibles que leur équivalent JavaScript, en tout cas, surtout pour un néophyte) et porteuses d&#8217;une richesse fonctionnelle délicieuse.  Voici quelques exemples :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="c1"># Modificateurs de fin de ligne : if/unless/while/until</span>
</span><span class='line'><span class="nx">runCallbacks</span><span class="p">()</span> <span class="k">if</span> <span class="nx">callbacksEnabled</span> <span class="nx">unless</span> <span class="nx">mode</span> <span class="o">is</span> <span class="s">&#39;silent&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Opérateur existentiel : vérifie d&#39;abord que client n&#39;est ni null ni undefined</span>
</span><span class='line'><span class="nx">client</span><span class="p">.</span><span class="nx">sendPacket</span> <span class="nx">bundle</span> <span class="k">if</span> <span class="nx">client</span><span class="o">?</span><span class="p">.</span><span class="nx">open</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># - Rest + spread sur les arguments supplémentaires à event</span>
</span><span class='line'><span class="c1"># - Compréhension de tableaux</span>
</span><span class='line'><span class="nv">trigger = </span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">args</span><span class="p">...)</span> <span class="o">=&gt;</span>
</span><span class='line'>  <span class="nx">observer</span><span class="p">.</span><span class="nx">notify</span> <span class="nx">args</span><span class="p">...</span> <span class="k">for</span> <span class="nx">observer</span> <span class="k">in</span> <span class="nx">@observers</span><span class="p">[</span><span class="nx">event</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># - Arguments par défaut</span>
</span><span class='line'><span class="c1"># - L&#39;absence d&#39;accolades autour de l&#39;objet d&#39;options donne</span>
</span><span class='line'><span class="c1">#   l&#39;impression d&#39;avoir des paramètres nommés :-)</span>
</span><span class='line'><span class="nv">fadeIn = </span><span class="p">(</span><span class="nv">speed = </span><span class="s">&#39;fast&#39;</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">@animate</span> <span class="nv">opacity: </span><span class="mi">1</span><span class="p">,</span> <span class="nv">speed: </span><span class="nx">speed</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Compréhension de tableau conditionnelle</span>
</span><span class='line'><span class="nv">foods = </span><span class="p">[</span><span class="s">&#39;broccoli&#39;</span><span class="p">,</span> <span class="s">&#39;spinach&#39;</span><span class="p">,</span> <span class="s">&#39;chocolate&#39;</span><span class="p">]</span>
</span><span class='line'><span class="nx">eat</span> <span class="nx">food</span> <span class="k">for</span> <span class="nx">food</span> <span class="k">in</span> <span class="nx">foods</span> <span class="k">when</span> <span class="nx">food</span> <span class="o">isnt</span> <span class="s">&#39;chocolate&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Tableau par intervalle (descendant !)</span>
</span><span class='line'><span class="nv">countdown = </span><span class="p">[</span><span class="mi">10</span><span class="p">..</span><span class="mi">1</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Boucle dédiée for…of (équivalent étendu du for…in de JS)</span>
</span><span class='line'><span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">prop</span><span class="si">}</span><span class="s"> is </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">value</span> <span class="k">of</span> <span class="nx">author</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Slicing de tableau</span>
</span><span class='line'><span class="nv">centerNames = </span><span class="nx">names</span><span class="p">[</span><span class="mi">2</span><span class="p">..</span><span class="mi">4</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># true peut se dire aussi on ou yes, selon ce qu&#39;on trouve naturel</span>
</span><span class='line'><span class="nx">launch</span><span class="p">()</span> <span class="k">if</span> <span class="nx">ignition</span> <span class="o">is</span> <span class="kc">on</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Comparaisons chaînées FTW!</span>
</span><span class='line'><span class="nv">inTheNorm = </span><span class="mi">80</span> <span class="o">&lt;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="mi">120</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># La POO classique devient super simple</span>
</span><span class='line'><span class="k">class</span> <span class="nx">Geek</span> <span class="k">extends</span> <span class="nx">Person</span>
</span><span class='line'>  <span class="nv">constructor: </span><span class="nf">(@name, @language = &#39;js&#39;) -&gt;</span>
</span><span class='line'>    <span class="k">super</span> <span class="nx">@name</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">code: </span><span class="o">-&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&quot;Hacking away in </span><span class="si">#{</span><span class="nx">@language</span><span class="si">}</span><span class="s">!&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Affectation destructurée simple : inversion de variables</span>
</span><span class='line'><span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">b</span><span class="p">,</span> <span class="nx">a</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Les regexes deviennent plus faciles à documenter/relire,</span>
</span><span class='line'><span class="c1"># grâce à une syntaxe de bloc.</span>
</span><span class='line'><span class="nv">OPERATOR = </span><span class="sr">///</span> <span class="sr">^ (</span>
</span><span class='line'><span class="sr">  ?: [-=]&gt;             </span><span class="c1"># function</span>
</span><span class='line'>   <span class="sr">| [-+*/%&lt;&gt;&amp;|^!?=]=  </span><span class="c1"># compound assign / compare</span>
</span><span class='line'>   <span class="sr">| &gt;&gt;&gt;=?             </span><span class="c1"># zero-fill right shift</span>
</span><span class='line'>   <span class="sr">| ([-+:])\1         </span><span class="c1"># doubles</span>
</span><span class='line'>   <span class="sr">| ([&amp;|&lt;&gt;])\2=?      </span><span class="c1"># logic / shift</span>
</span><span class='line'>   <span class="sr">| \?\.              </span><span class="c1"># soak access</span>
</span><span class='line'>   <span class="sr">| \.{2,3}           </span><span class="c1"># range or splat</span>
</span><span class='line'><span class="sr">) ///</span>
</span></code></pre></td></tr></table></div></figure>


<p>Vous trouverez le détail des syntaxes étendues <a href="http://coffeescript.org/">sur la page officielle</a>.  Ça fait rêver !</p>

<h2>Un workflow non pas ralenti, mais accéléré</h2>

<p>Ce n&#8217;est pas parce qu&#8217;on utilise un langage de plus haut niveau qu&#8217;on doit se taper la conversion manuellement avant chaque test.  Tout comme LESS, SASS ou Stylus pour les CSS, CoffeeScript propose un <strong>watcher</strong> qui surveille vos sources pour produire les versions JS correspondantes dès que les fichiers d&#8217;origine changent.</p>

<p>C&#8217;est naturellement combinable avec les principaux outils de traitement automatique (notamment l&#8217;enrobage en modules, la concaténation et le compactage) tels que Brunch, Yeoman, Grunt, CodeKit, Hammer, etc.</p>

<p>Quant au débogage, au-delà de la transparence très raisonnable dans la génération du code JavaScript, <strong>CoffeeScript sait produire des <a href="http://coffeescript.org/#source-maps">source maps</a></strong> qui permettent son <strong>débogage natif</strong>, par exemple dans Chrome (Developer Channel ou Canary).</p>

<h2>Le futur effectif de JavaScript</h2>

<p>CoffeeScript n&#8217;est pas une bidouille dans un coin, les délires syntaxiques d&#8217;un type qui sont voués à l&#8217;impasse et à l&#8217;oubli. C&#8217;est même tout le contraire…</p>

<p><strong>La popularité de CoffeeScript est telle</strong> que le TC-39 (groupe de travail au sein de l&#8217;ECMA chargé de spécifier les prochaines versions d&#8217;ECMAScript, et donc de JavaScript) recourt très régulièrement aux travaux de Jérémy sur CoffeeScript.  Ainsi, la syntaxe de classes, les expressions de fonctions comme la <em>fat arrow</em>, les affectations destructurées et d&#8217;autres aspects du langage trouvent, petit à petit, leur chemin dans <strong>ECMAScript 6</strong>, aux côtés d&#8217;autres évolutions majeures comme les proxies.</p>

<p>Faire du CoffeeScript ce n&#8217;est donc pas s&#8217;éloigner de JavaScript, mais bien plutôt <strong>s&#8217;habituer dès aujourd&#8217;hui à ce qu&#8217;on trouvera dans le JavaScript de demain</strong> !</p>

<h2>Formez-vous dès maintenant.  C&#8217;est le moment !</h2>

<p>Cet article ne vous a toujours pas assez donné envie ? Allez donc jouer sur l&#8217;excellente page principale du <a href="http://coffeescript.org/">site officiel</a>, avec ses démos exécutables détaillées et sa console « Try CoffeeScript » utilisable à n&#8217;importe quel moment.</p>

<p>Ensuite, prenez de l&#8217;avance sur la concurrence, valorisez vos compétences et gagnez en valeur ajoutée en assistant dès maintenant à nos <a href="http://www.js-attitude.fr/coffee-script/">formations CoffeeScript</a>.  Dotés d&#8217;un tarif imbattable et pouvant être prises en charge par vos DIF (comme toutes nos formations), elles sont un véritable cadeau à vous faire.</p>

<ul data-upcoming-sessions="coffee-script"></ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sublime Text 2 pour le dev web : config, trucs et astuces]]></title>
    <link href="http://www.js-attitude.fr/2013/03/12/sublime-text-dev-web-config-trucs-astuces/"/>
    <updated>2013-03-12T16:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2013/03/12/sublime-text-dev-web-config-trucs-astuces</id>
    <content type="html"><![CDATA[<h2>Pourquoi Sublime Text ?</h2>

<p>J’ai passé des années sur Emacs, puis sur Vim, puis sur TextMate.  Étant un développeur web sur OSX faisant beaucoup de Rails, TextMate était un choix évident, avec la pléthore d&#8217;astuces et d&#8217;outils petits et grands pour l&#8217;écriture de code Rails que ses paquets renferment…  En dépit de ses limitations (pas de <em>split view</em>, <em>fuzzy finder</em> lent à la mise à jour, plus d&#8217;évolution significative depuis des années), j&#8217;y suis donc resté obstinément, comme beaucoup.</p>

<p>Pendant ce temps, <a href="http://www.sublimetext.com/">Sublime Text</a> et sa version 2 (« ST2 » dans le reste de cet article) ont acquis petit à petit une renommée significative, au point que je voyais chaque jour davantage de profils similaires au mien qui passaient dessus et ne revenaient pas en arrière.  Lorsque je m&#8217;y suis mis moi aussi, j&#8217;ai pris soin de chercher tout de suite des ressources approfondies sur ST histoire de ne pas le sous-utiliser pendant des mois voire des années, comme le font souvent trop de gens avec un nouvel outil.</p>

<p>Et de fait, <strong>ça déchire</strong>.  Il y a bien sûr quelques petites frustrations de-ci de-là par rapport à TextMate (les snippets et la complétion pour l&#8217;univers Rails sont loin derrière ceux de TextMate, malgré des paquets similaires), mais les avantages écrasent les inconvénients.  Je suis surtout sensible à sa <strong>vitesse</strong> (le <em>fuzzy finder</em> est toujours à jour, instantanément, ce qui explose aussi bien celui natif à TextMate que le plugin PeepOpen, qui avait beaucoup de soucis), et l&#8217;outil est dispo sur OSX, Linux et Windows, ce qui permet de le standardiser dans une équipe multi-OS.  Quant à la possibilité d&#8217;étendre soi-même l&#8217;outil, elle est similaire à celle de TextMate.</p>

<p>Alors voyons en détail ce que j&#8217;adore chez ST, et comment je me le suis configuré.</p>

<!-- more -->


<p>Un dernier point : je vous encourage fortement à enregistrer votre licence de Sublime Text.  Bien sûr il est utilisable à 100% sans paiement (on se prend juste régulièrement une incitation à le payer), mais vu les énormes gains de productivité et de vitesse qu&#8217;il permet, je trouve tout-à-fait normal de rétribuer les auteurs.  Et après tout, $70 (jusqu&#8217;à $50 pour les gros volumes), ce n&#8217;est pas cher payé pour un tel avantage.</p>

<p>Pour finir, épargnez-moi les trolls à rallonge dans les commentaires sur la supériorité de tel ou tel éditeur.  Je fais toujours beaucoup de Vim, par exemple, notamment <em>via</em> des sessions SSH, et j&#8217;aime beaucoup cet éditeur (ST a d&#8217;ailleurs un <a href="http://www.sublimetext.com/docs/2/vintage.html">mode Vintage</a> qui lui rend hommage).  Il ne s&#8217;agit pas ici de dire que l&#8217;un est meilleur que l&#8217;autre, d&#8217;autant que comme souvent, les meilleurs outils sont ceux qu&#8217;on maîtrise le plus…  Restons sur le sujet, s&#8217;il vous plaît.</p>

<h2>Pourquoi cet article ?</h2>

<p>J&#8217;écris cet article parce qu&#8217;autant ST peut être extrêmement puissant et confortable, autant son installation par défaut (ST « nu », si vous voulez) n&#8217;en laisse pas paraître grand chose…  La <em>sidebar</em> est totalement dénuée d&#8217;options utiles au clic droit, on n&#8217;a pas de <em>transpose</em>, etc.  Et même ses fonctions natives puissantes, comme le Go To Anything, la Command Palette ou les Layouts, sont souvent bien peu utilisés, ou sous-employés.</p>

<p>L&#8217;idée est donc de mettre en place ici une config « musclée », et de vous fournir également des liens vers des ressources externes de qualité sur ST lui-même, au travers notamment de screencasts, qui constituent toujours une des meilleures approches pour découvrir un éditeur, car l&#8217;aspect visuel et animé est important ici.  Je peux affirmer que ces ressources m&#8217;ont vraiment permis d&#8217;avoir rapidement une utilisation efficace de ST, quelques jours à peine après avoir commencé à l&#8217;utiliser.</p>

<h2>À partir de zéro</h2>

<p><strong>Note importante</strong> : si vous avez déjà ST d&#8217;installé et de personnalisé, il peut être préférable de sauvegarder vos réglages et paquets.  Une approche un peu bourrine mais exhaustive consiste à sauvegarder son répertoire <code>Packages</code> entier, qui comprend et les paquets et les configurations par défaut (<code>Default</code>) et utilisateur (<code>User</code>).  Vous trouverez ce répertoire facilement en utilisant la commande <code>Preferences: Browse packages</code> de ST (par exemple avec <em>Tools > Command Palette</em>, puis tapez « browse »).  Sur OSX par exemple, il s&#8217;agit classiquement de <code>~/Library/Application Support/Sublime Text 2/Packages</code>.</p>

<h3>Installation</h3>

<p>Vous pouvez télécharger ST depuis son <a href="http://www.sublimetext.com/">site officiel</a>.  L&#8217;installation est toute simple, et il ne vous reste plus qu&#8217;à le lancer une première fois pour qu&#8217;il crée les répertoires de configuration nécessaires.</p>

<h3>Structure de la configuration</h3>

<p>Deux principes gouvernent la configuration de ST :</p>

<ol>
<li>Il s&#8217;agit simplement de fichiers JSON, qu&#8217;on édite directement, et qui sont pris en compte immédiatement à la sauvegarde (sauf pour de rares manips, auquel cas c&#8217;est précisé par l&#8217;auteur du paquet)</li>
<li>Il y a trois niveaux de configuration : globale et utilisateur et syntaxe.</li>
</ol>


<p>Le plus souvent, un paquet fournira les deux premiers niveaux : global et utilisateur.  La configuration globale du paquet (ou de ST) fournit généralement le détail des options possibles, parfois commentées, en détaillant leurs valeurs potentielles en commentaires.</p>

<p>L&#8217;idée est de <strong>ne pas modifier la configuration globale</strong>, que ce soit celle de ST ou d&#8217;un paquet, mais de <strong>surcharger la configuration voulue au niveau utilisateur</strong>, en n&#8217;y précisant que les réglages modifiés.  En effet, lors d&#8217;une mise à jour, les fichiers de configuration globaux peuvent parfaitement être remplacés ; si vos personnalisations y figuraient, vous les aurez donc perdues…  En les cantonnant à vos fichiers de préférences utilisateur, vous êtes assurés de les conserver.</p>

<p>Certains paquets s&#8217;appliquent à plusieurs syntaxes spécifiques et vous permettent alors une configuration par syntaxe.  C&#8217;est le cas par exemple de SublimeLinter, que nous verrons tout-à-l&#8217;heure, qui vous permet à tout instant d&#8217;éditer les préférences de <em>linting</em> pour la syntaxe appliquée au fichier actuellement ouvert.</p>

<p>Outre les options de configuration, dont l&#8217;extension conventionnelle est <code>.sublime-settings</code>, ST et ses paquets peuvent contenir d&#8217;autres éléments : les raccourcis clavier (<code>.sublime-keymap</code>), <em>snippets</em> de code (<code>.sublime-snippet</code>), commandes mises à disposition (<code>.sublime-commands</code>), options de menu (<code>.sublime-menu</code>) et bien d&#8217;autres encore.  Si le sujet vous intéresse, NetTuts+ a un bon didacticiel (quoiqu’un poil ancien) sur le sujet : <a href="http://net.tutsplus.com/tutorials/python-tutorials/how-to-create-a-sublime-text-2-plugin/">How to create a Sublime Text 2 plugin</a>.</p>

<h2>Killer features</h2>

<h3>Killer feature #1: navigation ultra-rapide</h3>

<p>C&#8217;est l&#8217;une des principales raisons pour utiliser ST.  Naviguer au travers des fichiers, commandes, méthodes, etc. est extrêmement rapide.  Vous retrouverez l&#8217;essentiel des commandes possibles, et leurs raccourcis, dans le menu <em>Goto</em>.</p>

<p><strong>Ouvrir un fichier</strong></p>

<p>La commande générique <em>Go To Anything</em> est accessible <em>via</em> <code>Cmd+P</code> sur Mac (<code>Ctrl+P</code> sur Linux/Windows).  Elle ouvre un <em>fuzzy finder</em> systématiquement à jour (si vous avez de nouveaux fichiers qui viennent de débarquer dans votre arborescence, par exemple), il ne reste donc plus qu&#8217;à taper des fragments significatifs du chemin/nom du fichier (la correspondance n&#8217;est pas uniquement sur le nom de base, mais sur le chemin, et l&#8217;ordre est important).  Inutile de taper des espaces entre les « fragments ».</p>

<p>Imaginons que vous avez un projet Ruby on Rails sous la main.  Vous ouvrez son dossier racine dans ST, ce qui en fait une sorte de projet <em>ad hoc</em>, avec tous les fichiers concernés dans la <em>sidebar</em>.  Supposons que vous souhaitiez ouvrir rapidement le modèle <code>Person</code>.  Après avoir tapé <code>Cmd+P</code>, si vous tapez simplement <code>pers</code>, vous verrez sans doute plusieurs fichiers : le modèle, le contrôleur, les vues, la migration, les tests, etc.  Vous pouvez naturellement recourir aux flèches verticales du clavier pour choisir au sein de cette liste, ou éditer votre saisie pour affiner, par exemle <code>ampers</code> va sans doute restreindre le choix à <code>app/models/person.rb</code>, et il ne vous reste plus qu&#8217;à valider.</p>

<p><img class="center" src="http://www.js-attitude.fr/images/st-fuzzy-finder.png" width="596" height="398" title="Le fuzzy finder de Sublime Text en pleine action" ></p>

<p>Ce qui est très sympa, c&#8217;est que ST affiche automatiquement le fichier actuellement sélectionné, en mode <em>preview</em> (pas encore d&#8217;onglet dédié et persistant), dans l&#8217;éditeur.  On peut ainsi s&#8217;assurer qu&#8217;on a bien le fichier voulu sous la main.  D&#8217;ailleurs, ST fait pareil quand on clique sur un fichier dans la <em>sidebar</em> : il l&#8217;affiche en mode <em>preview</em>, et si on clique sur d&#8217;autres il remplacera par ceux-ci au fil des clics.  Il faut un double-clic pour confirmer l&#8217;ouverture et en faire un onglet dédié.  Ainsi, on peut chercher un contenu interactivement à travers plusieurs fichiers sans pour autant « pourrir ses onglets ».</p>

<p>À ce sujet, la navigation entre onglets reprend les raccourcis usuels de l&#8217;OS ; par exemple, sur OSX, on utilisera comme d&#8217;habitude <code>Cmd+Alt+Gauche</code> et <code>Cmd+Alt+Droite</code> (<code>⌘⌥←</code> et <code>⌘⌥→</code>), de façon circulaire.  Les onglets sont par ailleurs numérotés de gauche, à droite, et on peut y accéder directement par <code>Cmd+1</code>, <code>Cmd+2</code>, etc.  Je trouve toutefois ça assez peu pratique, car dès que j&#8217;ai plusieurs onglets ouverts je ne retrouve pas instantanément leur position, et ça va plus vite de défiler au travers des onglets jusqu&#8217;à celui que je souhaite…</p>

<p><strong>Aller à une méthode</strong></p>

<p>Évidemment, tout bon éditeur de code se doit de permettre de naviguer entre les symboles principaux d&#8217;un fichier source, et généralement, ce sont des méthodes (dans un fichier Markdown, ce seraient les titres, par exemple).  ST ne fait pas exception à la règle et propose <code>Cmd+R</code> pour cela.  En fait il s&#8217;agit juste du bon vieux Go To Anything où ST a déjà tapé pour vous le symbole <code>@</code>, qui préfixe les recherches dans les symboles du fichier (au lieu du nom du fichier).</p>

<p><img class="center" src="http://www.js-attitude.fr/images/st-file-symbols.png" width="598" height="86" title="Le fuzzy finder de Sublime Text sur les symboles du fichier" ></p>

<p>Ainsi, si tu es sur ton modèle <code>Person</code> qui a, disons, les méthodes <code>full_name</code>, <code>full_address</code>, <code>authenticate</code> et <code>disable</code>, et que tu fais <code>Cmd+R</code> puis que tu tapes <code>fa</code>, tu vas automatiquement filtrer sur <code>full_address</code>, ça va faire défiler le fichier directement à cet endroit-là (ce qui permet d&#8217;être sûr qu&#8217;on est bien là où on voulait…), y&#8217;a plus qu&#8217;à valider avec <code>Entrée</code>.  Elle est pas belle la vie ?</p>

<p><strong>Combiner les deux</strong></p>

<p>Ce que beaucoup d&#8217;utilisateurs de ST ne percutent pas, et c&#8217;est bien dommage, c&#8217;est qu&#8217;on peut parfaitement combiner la navigation vers un fichier <strong>et</strong> vers une de ses méthodes, en une seule opération.  Il y a là de quoi gagner quelques précieuses secondes, qui à l&#8217;échelle de la journée font tout plein de minutes qu&#8217;on pourra passer à quelque chose d&#8217;un peu plus directement productif que de naviguer dans son code…</p>

<p>Il suffit de faire un <code>Cmd+P</code>, de taper le nécessaire pour filtrer sur le fichier voulu, et de taper manuellement le <code>@</code> qui passe en mode « interne au fichier », puis le nécessaire au filtrage de méthode.  Toujours en prenant mon exemple d&#8217;application Rails avec son modèle Person, je pourrais ouvrir directement le fichier modèle sur la méthode <code>full_address</code> en faisant <code>Cmd+P</code> et en tapant quelque chose comme <code>ampers@fa</code> (qui ne correspondra qu&#8217;à <code>app/models/person.rb@full_address</code>).  Ooooouh que ça va vite, dis donc !</p>

<p><strong>Aller à une ligne précise</strong></p>

<p>Pouvoir aller rapidement à une ligne précise d&#8217;un fichier est très utile en développement vu qu&#8217;on se prend en permanence des infos sur les lignes : exceptions et erreurs, diffs, etc.  On peut bien sûr faire défiler le fichier jusqu&#8217;à plus soif, mais ça va plus vite en visant directement la ligne.  Chez ST, c&#8217;est <code>Ctrl+G</code> qui s&#8217;en occupe.  Il s&#8217;agit là aussi en fait d&#8217;un Go To Anything où ST aura rentré pour vous le symbole <code>:</code>, qui préfixe un numéro de ligne.  Y&#8217;a plus qu&#8217;à taper le numéro, ST défile en temps réel pour centrer verticalement l&#8217;éditeur sur la ligne visée, il ne reste plus qu&#8217;à valider.</p>

<p>Et bien sûr, là aussi tu peux combiner en une navigation l&#8217;ouverture d&#8217;un fichier et le placement sur une ligne.  Si Rails me dit que j&#8217;ai un souci ligne 12 dans mon modèle <code>Person</code>, je peux faire <code>Cmd+P</code> et taper <code>ampers:12</code>, paf !</p>

<p><strong>Rechercher une commande</strong></p>

<p>Même s&#8217;il y a déjà de nombreuses commandes visibles dans les menus de ST, il y en a encore beaucoup, beaucoup plus qui ne sont pas dotées d&#8217;une option de menu.  Heureusement, il y a la <em>Command Palette</em>, accessible via <code>Cmd+Shift+P</code> (pour rappel, <em>Shift</em> ou <em>Maj</em>, c&#8217;est la majuscule temporaire, hein…).  Tu te demandes ce que tu as comme possibilités de formatage ? Tape donc <code>format</code>, tu verras bien (en l&#8217;occurrence je n&#8217;ai que <em>Format: JavaScript</em>, qui vient du paquet JsFormat, lequel n&#8217;est pas là par défaut).</p>

<p>C&#8217;est une manière pratique de retrouver le raccourci clavier d&#8217;une commande.  Du coup, si tu dois retenir <em>un seul raccourci</em>, retiens <code>Cmd+Shift+P</code> : il te permettra de retrouver tous les autres :-)  Tu ne sais pas s&#8217;il existe un raccourci pour poser un <em>bookmark</em>, ou tu ne te rappelles plus ce que c&#8217;est ? Hop, <code>Cmd+Shift+P</code>, <code>bo</code> et tu vois tout de suite que <em>Bookmarks: Toggle</em> est associé <code>Cmd+F2</code>.</p>

<p>Personnellement, je me sers surtout de la <em>Command Palette</em> pour changer de syntaxe sur un fichier dont l&#8217;extension n&#8217;est pas reconnue (ou pas correctement), ou sur un buffer non sauvegardé dans un fichier.  Ainsi, quand je veux montrer un morceau de code JS à la volée en profitant d&#8217;un éditeur confortable et d&#8217;une coloration syntaxique au poil, je ne reste pas dans la console, j&#8217;ouvre un nouvel onglet et je fais <code>Cmd+Shift+P</code>, <code>syjs</code>, <code>Entrée</code>, ce qui active la commande <em>Syntax: JavaScript</em>, et le tour est joué !</p>

<h3>Killer feature #2: curseurs multiples</h3>

<p>On touche là à l&#8217;autre fonctionnalité la plus plebiscitée de ST.  Il s&#8217;agit d&#8217;un mécanisme qui va nous permettre d&#8217;<strong>éditer plusieurs endroits d&#8217;un fichier à la fois</strong> ; soit parce qu&#8217;on change un fragment identique à plusieurs endroits, soit plus généralement pour appliquer une saisie ou suppression identique à plusieurs endroits (par exemple, afin d&#8217;enrober plusieurs lignes par des balises ouvrante et fermante identiques).  C&#8217;est d&#8217;ailleurs la toute première fonctionnalité illustrée sur le site officiel.</p>

<p>Il existe deux grands cas de figure.</p>

<p><strong>Remplacement local d&#8217;un identifiant</strong></p>

<p>Identifiant ou morceau de texte quelconque, s&#8217;entend…  Il vous suffit de le sélectionner une première fois (idéalement à sa première apparition pertinente, ça évitera du <em>wrapping</em>), après quoi tout dépend de la pertinence des autres occurrences.  Si toutes les occurrences dans le fichier sont à manipuler pareil, on peut faire un Quick Find All (<code>Cmd+Ctrl+G</code>), qui les sélectionnera toutes et initialisera un curseur par occurrence.  Si seules les quelques occurrences qui suivent sont utiles, on préférera Quick Add Next (<code>Cmd+D</code>), le nombre de fois nécessaire.  Si seules certaines occurrences sont utiles, et pas forcément consécutives, on maintiendra <code>Cmd</code> enfoncé en sélectionnant les occurrences voulues (comme toujours, un double-clic sélectionnera automatiquement le « mot » sous le curseur).</p>

<p>Une fois chaque sélection mise en place et dotée d&#8217;un curseur, toute saisie effectuée (déplacements, frappe, suppression, etc.), retours chariot compris, sera reflétée sur tous les curseurs.  Un renommage massif est donc très simple.  Quand on a terminé, on presse <code>Esc</code>.</p>

<p><strong>Saisie à de multiples endroits</strong></p>

<p>Imaginons que vous ayez quelques lignes dans votre texte :</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>hello
</span><span class='line'>world
</span><span class='line'>this
</span><span class='line'>is
</span><span class='line'>nice</span></code></pre></td></tr></table></div></figure>


<p>Vous souhaitez les convertir en un tableau de chaînes JavaScript.  Rien de plus simple avec les curseurs multiples :</p>

<ol>
<li>Placez le curseur au début de la première ligne</li>
<li>Maintenez <code>Ctrl</code> enfoncé et descendez avec la flèche de curseur jusqu&#8217;au début de la dernière ligne</li>
<li>Voilà, vous avez 5 curseurs synchronisés</li>
<li>Tapez l&#8217;apostrophe ouvrante qui sera reflétée pour chaque chaîne</li>
<li>Pressez la combinaison de touches, ou la touche, permettant d&#8217;aller en fin de ligne (touche <code>Fin</code> ou <code>Cmd+Droite</code>, par exemple) ; tous les curseurs vont en fin de ligne, indépendamment des longueurs de ligne individuelles.</li>
<li>Tapez l&#8217;apostrophe fermante, puis la virgule, l&#8217;espace et enfin soit pressez <code>Suppr</code> soit sélectionnez le retour chariot et supprimez-le, ce qui ramène les lignes en une seule</li>
<li>Sélectionnez l&#8217;ensemble de la ligne et tapez <code>[</code> ; si vous êtes dans une syntaxe compatible (dont JavaScript), la sélection sera encadrée par les crochets.</li>
<li>Il ne vous reste plus qu&#8217;à supprimer la virgule finale dans le tableau (votre curseur doit être juste à côté, déplacez-le une fois pour déselectionner d&#8217;abord)</li>
</ol>


<p>Il est possible de procéder de façon légèrement différente en utilisant le Split Selection Into Lines, ce qui peut sembler plus rapide.  En repartant du texte de base, les 6 premières étapes ci-dessus deviennent les 5 ci-dessous :</p>

<ol>
<li>Sélectionnez les cinq lignes</li>
<li>Pressez <code>Cmd+Shift+L</code> ; chaque ligne devient une sélection distincte</li>
<li>Tapez l&#8217;apostrophe : chaque ligne étant une sélection, l&#8217;apostrophe encadre chaque sélection</li>
<li>Allez en fin de ligne (tous les curseurs suivent)</li>
<li>Tapez la virgule puis sélectionnez la fin de ligne (Shift+Droite) et tapez une espace pour les remplacer</li>
</ol>


<p>À vous de jouer avec les différentes possibilités et de déterminer ce qui vous semble le plus confortable selon la situation et la manipulation à effectuer.</p>

<h3>Killer feature #3: layouts &amp; focus groups</h3>

<p>Lorsqu&#8217;on vient d&#8217;éditeurs comme Emacs ou Vim, disposer de plusieurs vues simultanées, qu&#8217;il s&#8217;agisse de fichiers distincts ou de plusieurs portions du même fichier, est vite indispensable.  TextMate n&#8217;a pas réussi à nous donner ça (pas assez vite en tout cas), et ST fournit une gestion potable, même si elle ne permet pes des layouts très avancés (on a des plugins qui font ça, ceci dit ; les fans du <em>split</em> de Vim trouveront sans doute leur bonheur avec <a href="http://www.macdrifter.com/2012/07/sublime-text-working-with-multiple-panes.html">Origami</a>, par exemple).</p>

<p>Le principe de base est le <strong>layout</strong>. ST propose, <em>via</em> son menu <em>View > Layout</em>, 7 possibilités :</p>

<ul>
<li>Une seule vue (mode par défaut)</li>
<li>Layout horizontal à 2, 3 et 4 colonnes</li>
<li>Layout vertical à 2 ou 3 lignes</li>
<li>Layout grille en 2 &times; 2</li>
</ul>


<p>Les raccourcis clavier ont tous une base <code>Cmd+Alt+num</code> (1, 2, 3, 4 et pour la grille 5), avec <code>Shift</code> en plus (et 2 ou 3) pour les layouts verticaux.  Évidemment, sur un laptop au clavier français, les raccourcis à base de <code>Shift+num</code> ne marcheront pas, le <code>Shift</code> étant déjà nécessaire pour accéder aux nombres…</p>

<p>Chaque panneau du layout est ce qu&#8217;on appelle un <strong>focus group</strong>.  Il est alors possible de placer les onglets dans le focus group de son choix, soit par simple glisser-déplacer, soit en activant l&#8217;onglet et en utilisant le raccourci qui va bien (<code>Ctrl+Shift+num</code>).  On peut également changer le <em>focus group</em> actif au clavier (<code>Ctrl+num</code>).  Lorsqu&#8217;on réduit le nombre de <em>focus groups</em>, les onglets présents dans ceux qui dégagent se voient agrégés aux groupes restants.  Lors de l&#8217;ouverture d&#8217;un onglet, celui-ci apparaît dans le groupe qui était actif à ce moment-là.</p>

<p>Pour voir deux morceaux d&#8217;un fichier en parallèle, il suffit d&#8217;ouvrir à nouveau le fichier dans un autre groupe.  Les deux vues sont synchronisées en termes de contenu : ce que vous tapez dans l&#8217;un est retranscrit directement dans l&#8217;autre.</p>

<h3>Et tellement, tellement plus…</h3>

<p>Sans même aller chercher des paquets en plus, ST a des tas de petits détails appréciables.  Sa gestion du rechercher-remplacer, par exemple, au sein d&#8217;un fichier comme au global (basée sur Ack), est excellente.  Ainsi, il affiche en temps réel les correspondances lors de l&#8217;élaboration d&#8217;une recherche par expression rationnelle, ce qui permet d&#8217;éviter d&#8217;y aller à l&#8217;aveugle.  Il est possible de pré-remplir les champs de recherche et remplacement depuis l&#8217;éditeur lui-même, afin de gagner du temps.  Plein de petites choses sympa comme ça.</p>

<h2>Réglages de l&#8217;indentation</h2>

<p>Quand on parle d&#8217;indentation, c&#8217;est tout de suite chacun son style…  Le seul sujet où tout le monde est à peu près d&#8217;accord, c&#8217;est : « oui, indenter correctement c&#8217;est une bonne chose ».  Ce qui est amusant, c&#8217;est que ça n&#8217;empêche pas une bonne partie de gens d&#8217;avoir des boutons à l&#8217;idée que leur langage <strong>exige</strong> une indentation correcte (Python, CoffeeScript, HAML, Jade, etc.) :-)</p>

<p>En tous les cas, lorsqu&#8217;il s&#8217;agit de l&#8217;indentation et de la gestion des espacements d&#8217;une manière générale, ST propose plusieurs fonctionnalités et réglages, ainsi qu&#8217;un menu déroulant dédié à l&#8217;indentation en bas à droite de la fenêtre, juste avant le choix de syntaxe :</p>

<p><img class="center" src="http://www.js-attitude.fr/images/st-indentation-menu.png" title="w h Le menu d’indentation de Sublime Text" ></p>

<h3>Réglages automatiques en fonction du contenu du fichier</h3>

<p>Le réglage <code>detect_indentation</code>, qui est à <code>true</code> par défaut, fait qu&#8217;à chaque ouverture de fichier, ST va tenter de détecter les réglages d&#8217;indentation à appliquer.  L&#8217;idée est de faciliter le respect du style en vigueur dans le fichier.  Le type de caractère employé ainsi que la taille de l&#8217;indentation seront automatiquement ajustés.  Si vous avez recalé ce réglage à <code>false</code>, vous pouvez néanmoins exécuter cette détection manuellement pour le fichier en cours en choisissant <em>Guess Settings From Buffer</em> dans le menu d&#8217;indentation de la barre d&#8217;état.</p>

<h3>Réglages par syntaxe</h3>

<p>L&#8217;exécution de l&#8217;indentation exploite plusieurs réglages :</p>

<ul>
<li>Le <em>type de caractère employé</em> : tabulation ou espaces.  Le réglage correspondant s&#8217;appelle <code>translate_tabs_to_spaces</code> : s&#8217;il vaut <code>true</code>, on utilise des espaces, sinon des tabulations.</li>
<li>La <em>taille</em> de l&#8217;indentation, en caractères affichés.  On peut mettre ce qu&#8217;on veut mais les réglages les plus fréquents sont 2 et 4.  C&#8217;est le rôle du réglage <code>tab_size</code>.</li>
<li>Le <em>comportement en cas de retour arrière</em> (<em>BackSpace</em>).  Quand le réglage <code>use_tab_stops</code> est à <code>true</code>, le retour arrière ramène au dernier taquet d&#8217;indentation (d&#8217;après <code>tab_size</code>).</li>
<li>L&#8217;<em>indentation automatique</em>.  Nous la couvrirons dans un instant.</li>
</ul>


<p>Ces réglages sont définis, par défaut, pour chaque syntaxe.  Lorsque vous les changez interactivement via la partie inférieure droite de la barre d&#8217;état (juste à gauche du sélecteur de syntaxe), ces réglages persistent pour la syntaxe en vigueur, sauf si vous êtes en détection automatique comme vu précédemment.  Vous pouvez les modifier au travers de vos réglages par syntaxe (dans le menu <em>Preferences > Settings - More > Syntax-specific - User</em>).</p>

<h3>Conversion de l&#8217;indentation</h3>

<p>Si votre fichier utilise un autre caractère d&#8217;indentation, ou (plus souvent) un mix embarassant d&#8217;espaces et de tabulations, vous pouvez recaler vers le caractère voulu au moyen des deux options du menu d&#8217;indentation <em>Convert Indentation to Spaces</em> et <em>Convert Indentation to Tabs</em>.  Toutefois, cela ne renormalise pas l&#8217;indentation structurelle : il vous faudra pour cela un paquet de formatage dédié à votre syntaxe.  Pour JavaScript, j&#8217;utilise comme nous le verrons plus tard JsFormat.</p>

<h3>Indentation automatique</h3>

<p>Sans nécessiter de paquet complémentaire, ST est tout de même capable d&#8217;observer certaines règles d&#8217;indentation automatique, c&#8217;est-à-dire de définition de l&#8217;indentation à employer lorsque vous créez une nouvelle ligne (en général en pressant <code>Entrée</code>).  Les réglages concernés sont :</p>

<ul>
<li>L&#8217;activation de l&#8217;indentation automatique : <code>auto_indent</code> (qui est à <code>true</code> par défaut).</li>
<li>Les améliorations standard à cette indentation automatique : <code>smart_indent</code> (également active par défaut).  Détecte que vous venez d&#8217;entrer dans un bloc, par exemple, et augmente tout seul le niveau d&#8217;indentation.</li>
<li>L&#8217;alignement des paramètres sur plusieurs lignes : <code>indent_to_bracket</code>.  Heureusement désactivé par défaut (je déteste ça), ce réglage insère automatiquement l&#8217;indentation variable nécessaire si, au sein d&#8217;une déclaration de fonction par exemple, vous allez à la ligne au milieu de la liste de paramètres et voulez que la nouvelle ligne démarre alignée avec le premier paramètre de la précédente :</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">uglyFormat</span><span class="p">(</span><span class="nx">message</span><span class="p">,</span> <span class="nx">targets</span><span class="p">,</span>
</span><span class='line'>                    <span class="nx">options</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Comme diraient nos amis anglophones : <em>« what the—  I don&#8217;t even— ?! »</em>.  Mais bon, les goûts et les couleurs, hein…</p>

<h3>Espaces de fin de ligne et de fin de fichiers</h3>

<p>Il ne s&#8217;agit pas à proprement parler d&#8217;indentation mais on retrouve souvent ces réglages documentés/discutés au sein de l&#8217;indentation en ce qui concerne ST.  Trois réglages gèrent ces espaces :</p>

<ul>
<li><code>trim_automatic_white_space</code> s&#8217;assure que lorsque le curseur quitte une ligne où ST a inséré automatiquement une indentation derrière laquelle il n&#8217;y a finalement rien, cette indentation automatique est dégagée pour ne pas laisser d&#8217;espace de fin de ligne qui n&#8217;aurait pas été ajouté explicitement par l&#8217;utilisateur.  C&#8217;est actif par défaut.</li>
<li><code>trim_trailing_white_space_on_save</code> est à mon sens <strong>indispensable</strong> : activé, ce réglage s&#8217;assure à la sauvegarde du buffer que tout espacement de fin de ligne est dégagé.  Mais comment vit-on sans ?!</li>
<li><code>ensure_newline_at_eof_on_save</code> est un petit réglage bien utile qui s&#8217;assure à la sauvegarde que le fichier se termine par une ligne vide.  On s&#8217;est tous pris des <em>diffs</em> pourris par un <em>« No newline at end of file »</em> sous prétexte qu&#8217;on a changé la fin du fichier, qu&#8217;il avait une ligne vide avant et plus maintenant, ou inversement.  Ce réglage normalise ça automatiquement (autre bonus : un <code>cat</code> sur le fichier ramènera toujours le prompt en début de ligne ;-)).</li>
</ul>


<h2>Package Control et paquets recommandés</h2>

<p>Déjà, premier truc à faire, s&#8217;assurer qu&#8217;on a installé <a href="http://wbond.net/sublime_packages/package_control">Package Control</a>.  C&#8217;est une sorte de gestionnaire de paquets pour ST.  Il ne connaît pas <em>tous</em> les paquets possibles (n&#8217;importe qui peut coller un paquet quelque part sur le web, on n&#8217;a pas besoin de notifier Package Control), mais pour ceux qu&#8217;il connaît, il est nettement plus pratique que de chercher le paquet en ligne et l&#8217;installer à la main…</p>

<p>L&#8217;installation de Package Control est l&#8217;une des rares manips qui nécessitera le redémarrage de ST, ainsi que l&#8217;utilisation de la console de ST.</p>

<ol>
<li>Ouvrez la console de ST.  Le raccourci clavier ne marche pas dans tous les environnements, je vous invite donc à juste aller dans le menu <em>View > Show Console</em>.</li>
<li>Ça affiche une zone claire en bas de la fenêtre, prête à la saisie.  Copiez-collez le code Python indiqué sur <a href="http://wbond.net/sublime_packages/package_control/installation">la page d&#8217;installation</a> et validez</li>
<li>La console va bosser quelques secondes et vous afficher au final « Please restart Sublime Text to finish installation ».  Redémarrez ST.</li>
</ol>


<p>À présent, vous avez accès à l&#8217;installation et la gestion des paquets <em>via</em> Package Control juste en lançant la <em>Command Palette</em> (<code>Cmd+Shift+P</code> ou <code>Ctrl+Shift+P</code>) et en tapant « Package ».  Vous verrez toute une liste de commandes pour installer, désinstaller, mettre à jour, activer, désactiver, lister des paquets, et j&#8217;en passe.  Les commandes affichent leur déroulement dans la barre d&#8217;état, sur la gauche.</p>

<h3>Mes paquets supplémentaires chéris</h3>

<p>Voici ma liste de paquets Sublime Text recommandés, par ordre alphabétique.</p>

<p><strong>AdvancedNewFile</strong> (<a href="https://github.com/skuroda/Sublime-AdvancedNewFile">détails</a>)</p>

<p>Permet de créer un fichier au clavier depuis n&#8217;importe où, au moyen du raccourci clavier associé (par défaut <code>Cmd+Alt+N</code> ou <code>Ctrl+Alt+N</code>).  Dans la zone de saisie qui apparaît en bas de la fenêtre, on peut alors taper le chemin qu&#8217;on veut (si on est dans un projet ou pseudo-projet, la racine implicite est celle de celui-ci), la complétion étant disponible.  Si on tape des noms de dossier inexistants, ils seront créés à la volée.</p>

<p>Je m&#8217;en sers pour aller plus vite qu&#8217;en reprenant la souris / le trackpad pour dérouler mes divers niveaux de dossier et enfin faire clic droit + <em>New File</em>.</p>

<p><a href="http://net.tutsplus.com/tutorials/tools-and-tips/lightning-fast-folder-and-file-creation-in-sublime-text-2/">Voici un court screencast qui illustre bien AdvancedNewFile</a></p>

<p><strong>Alignment</strong> (<a href="http://wbond.net/sublime_packages/alignment">détails</a>)</p>

<p>Permet d&#8217;homogénéiser l&#8217;indentation de plusieurs lignes ou sélections (eh oui, souvenez-vous, on a les curseurs multiples !) mais je m&#8217;en sers principalement pour aligner les <code>=</code> de plusieurs lignes adjacentes (et donc, au passage, les <code>=&gt;</code> de Ruby).  Il suffit de sélectionner les lignes en question et de presser <code>Cmd+Ctrl+A</code> (OSX) ou <code>Ctrl+Alt+A</code> (autres).  Ça transforme par exemple le foutoir suivant :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">name</span> <span class="o">=</span> <span class="vi">@customer</span><span class="o">.</span><span class="n">full_name</span>
</span><span class='line'>  <span class="n">capacity</span>    <span class="o">=</span> <span class="vi">@customer</span><span class="o">.</span><span class="n">plan</span><span class="o">.</span><span class="n">quota</span>
</span><span class='line'><span class="n">addressee</span> <span class="o">=</span> <span class="n">capacity</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="nb">name</span> <span class="p">:</span> <span class="vi">@customer</span><span class="o">.</span><span class="n">plan</span><span class="o">.</span><span class="n">admin</span><span class="o">.</span><span class="n">full_name</span>
</span></code></pre></td></tr></table></div></figure>


<p>…en ceci (en deux temps : la première fois, ça homogénéise l&#8217;indentation, la seconde ça aligne les <code>=</code>) :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">name</span>      <span class="o">=</span> <span class="vi">@customer</span><span class="o">.</span><span class="n">full_name</span>
</span><span class='line'><span class="n">capacity</span>  <span class="o">=</span> <span class="vi">@customer</span><span class="o">.</span><span class="n">plan</span><span class="o">.</span><span class="n">quota</span>
</span><span class='line'><span class="n">addressee</span> <span class="o">=</span> <span class="n">capacity</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="nb">name</span> <span class="p">:</span> <span class="vi">@customer</span><span class="o">.</span><span class="n">plan</span><span class="o">.</span><span class="n">admin</span><span class="o">.</span><span class="n">full_name</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>CoffeeScript</strong> (<a href="https://github.com/Xavura/CoffeeScript-Sublime-Plugin">details</a>)</p>

<p>Prise en charge complète de <a href="http://coffeescript.org">CoffeeScript</a>, le petit langage qui tue par-dessus JavaScript.  Outre que j&#8217;en fais tout le temps, il est bien pratique lors de la <a href="http://www.js-attitude.fr/coffee-script/">formation</a>, puisqu&#8217;il propose entre autres un mode <em>Watch</em> qui maintient en temps réel le résultat du <em>transpiling</em> vers JS dans un buffer.  En combinant avec la vue horizontale à deux panneaux, j&#8217;ai donc du <em>live transpiling</em> cash dans mon éditeur, ce qui est top :-)</p>

<p><strong>Emmet</strong> (<a href="http://emmet.io/">détails</a>) — <strong>indispensable !</strong></p>

<p>Emmet est en quelque sorte le successeur de Zen Coding.  Il fournit de très nombreuses aides à la saisie pour HTML et CSS, en proposant d&#8217;une part des syntaxes ultra-courtes pour générer une tonne de code souhaité, et d&#8217;autre part de nombreuses actions de manipulation du code existant.  Une fois qu&#8217;on s&#8217;y est mis, on ne revient pas en arrière…</p>

<p>Pour vous en convaincre, jetez donc un œil à la <a href="http://emmet.io/">vidéo</a> et aux <a href="http://docs.emmet.io/">docs</a>.</p>

<p><strong>Gitconfig</strong> (<a href="https://github.com/lifted-studios/Gitconfig.tmLanguage">détails</a>)</p>

<p>Coloration syntaxique pas trop naze pour mes fichiers de configuration Git (<code>~/.gitconfig</code> et <code>.git/config</code>), parce que d&#8217;abord.</p>

<p>Ce paquet n&#8217;est pas connu de Package Control.  Le plus simple pour l&#8217;installer est d&#8217;ouvrir une ligne de commande dans le répertoire de paquets de ST (accessible notamment en faisant <em>Settings > Browse packages</em>), et d&#8217;y décompresser le Zip du paquet ou d&#8217;y clôner son dépôt Git.  Le paquet est pris en charge automatiquement par ST.</p>

<p>Vous pouvez donc :</p>

<ul>
<li>Clôner le dépôt si vous utilisez déjà Git</li>
<li>Récupérer le Zip et le décompresser dans le cas contraire ; la page de dépôt Github propose à gauche des URLs de clonage un bouton &#8220;Zip&#8221; bien en évidence, qui vous fournit l&#8217;archive correspondante.</li>
</ul>


<p><strong>GitGutter</strong> (<a href="http://www.jisaacks.com/gitgutter">détails</a>)</p>

<p>Affiche dans la goutière (la barre verticale à gauche du texte qui contient les numéros de lignes, marqueurs de <em>bookmarks</em>, etc.) des marqueurs de modification Git (insertions, modifications, suppressions).  Ce n&#8217;est pas <em>indispensable</em>, mais lorsque je suis en train de bosser sur un commit long, de résoudre un conflit ou d&#8217;examiner un diff, ça me permet de tout de suite voir les lignes concernées, ou de remarquer que des lignes ont l&#8217;air d&#8217;avoir bougé alors qu&#8217;elles n&#8217;auraient pas dû, etc.</p>

<p><strong>Haml</strong> (<a href="https://github.com/phuibonhoa/handcrafted-haml-textmate-bundle">détails</a>)</p>

<p>Prise en charge complète de <a href="http://haml.info/">Haml</a>, un langage de templating que j&#8217;utilise systématiquement sur mes projets Rails.  Fournit la coloration syntaxique, les <em>snippets</em> et <em>tab triggers</em>, les raccourcis claviers, etc.</p>

<p><strong>Handlebars</strong> (<a href="https://github.com/daaain/Handlebars">details</a>)</p>

<p>Coloration syntaxique pour le langage de <em>templating</em> <a href="http://handlebarsjs.com/">Handlebars</a>, que j&#8217;utilise beaucoup en formation (<a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> et <a href="http://www.js-attitude.fr/js-total/">JS Total</a>).  Bonne qualité de coloration et de contraste plus <em>tab triggers</em> (morceaux dynamiques de code déclenchables par tabulation) pour les blocs les plus courants.</p>

<p><strong>Jade</strong> (<a href="https://github.com/davidrios/jade-tmbundle">détails</a>)</p>

<p>Coloration syntaxique pour <a href="http://jade-lang.com/">Jade</a>, un langage de templating côté client (orienté environnements JavaScript, quoi) très similaire à HAML, que j&#8217;utilise de préférence à Handlebars.</p>

<p><strong>JsFormat</strong> (<a href="https://github.com/jdc0589/JsFormat">détails</a>)</p>

<p>Il s&#8217;agit d&#8217;une sorte de surcouche par-dessus l&#8217;excellent <a href="http://jsbeautifier.org/">JS Beautifier</a>, qui permet de reformater du JS en se conformant à un certain nombre de réglages qui définissent un <em>coding style</em>.  Calé sur un raccourci-clavier (<code>Ctrl+Alt+F</code> par défaut), il est notamment très pratique pour formatter vite fait une grappe JSON renvoyée par une API ou « déminifier » un code récupéré sur un site en production.</p>

<p><strong>LoremIpsum</strong> (<a href="https://github.com/billymoon/LoremIpsum">détails</a>)</p>

<p>On a tous besoin d&#8217;un générateur de texte aléatoire dans nos éditeurs, surtout ceux qui font du développement web front…  Ce petit paquet remplit bien son office, avec une insertion calée sur <code>Cmd+Alt+L</code>, qu&#8217;on peut répéter autant de fois qu&#8217;on veut pour avoir des textes supplémentaires (qui démarrent toutefois tous par « Lorem ipsum »).  On a également un <em>tab trigger</em> basé sur « lorem ».  Des réglages permettent de définir la taille des fragments insérés (un peu, pas mal, beaucoup…), et des commandes dédiées par taille sont également accessibles dans la <em>Command Palette</em>.</p>

<p><strong>Sass</strong> (<a href="https://github.com/nathos/sass-textmate-bundle">détails</a>)</p>

<p>Une bonne partie de mes CSS sont en <a href="http://sass-lang.com/">SASS</a> (plus exactement en syntaxe SCSS), j&#8217;ai donc besoin d&#8217;une coloration syntaxique valable et, idéalement, d&#8217;une aide à la saisie (le paquet fournit une saisie des propriétés basée sur <a href="https://code.google.com/p/zen-coding/wiki/ZenCSSPropertiesEn">les raccourcis Zen Coding</a>).</p>

<p><strong>SideBarEnhancements</strong> (<a href="https://github.com/titoBouzout/SideBarEnhancements">détails</a>) — <strong>indispensable !</strong></p>

<p>Je sais pas comment je vivrais sans celui-là.  Le menu contextuel de la <em>sidebar</em> dans ST « nu » est consternant : on ne peut pratiquement rien faire.  Grâce à ce paquet, on a une tonne de commandes super pratiques, souvent associées à des raccourcis clavier.</p>

<p><em>Open with</em>, <em>Rename</em>, <em>Move</em>, etc. mais aussi les nombreuses options de <em>Copy as Text</em>, <em>Duplicate</em>, <em>Open in Browser</em> (raccourcis super simples, idéal pour ouvrir immédiatement le document HTML/SVG dans un navigateur), <em>Find Advanced</em>…  Une vraie mine d&#8217;or pour des manips qu&#8217;on fait d&#8217;ordinaire à la main au moyen d&#8217;une ligne de commande parfois complexe.</p>

<p><strong>SmartMarkdown</strong> (<a href="https://github.com/demon386/SmartMarkdown">détails</a>)</p>

<p>La prise en charge de Markdown par ST est très, très light.  On a une partie de la coloration syntaxique, et c&#8217;est tout.  Je n&#8217;ai pas encore trouvé une super coloration et une bonne gestion de raccourcis-clavier pour le gras, l&#8217;italique, le code, les liens, etc.  mais au moins avec ce paquet j&#8217;ai des aides <em>structurelles</em> vraiment sympa : <em>folding</em> pas mal foutu sur les niveaux de titre, continuation automatique des listes (ordonnées ou non), navigation par titre, gestion des tableaux en convention Pandoc, etc.</p>

<p><strong>Stylus</strong> (<a href="https://github.com/billymoon/Stylus">détails</a>)</p>

<p>Je fais de plus en plus de CSS en <a href="http://learnboost.github.com/stylus/">Stylus</a> plutôt qu&#8217;en <a href="http://sass-lang.com/">SASS</a>, pour la même raison que je fais du <a href="http://jade-lang.com/">Jade</a> : de moins en moins de bruit syntaxique, de plus en plus d&#8217;expressivité.  Il me faut évidemment une coloration syntaxique à la hauteur (capable de s&#8217;y retrouver avec beaucoup moins de « marqueurs » que d&#8217;habitude) et, idéalement, un accès direct au <em>transpiling</em> vers CSS.</p>

<p>Ce paquet a quelques dépendances externes (sur OSX, il lui faut le « binaire » <code>stylus</code> obtensible par installation globale du paquet npm homonyme), mais c&#8217;est bien normal vu que la complexité d&#8217;analyse syntaxique est suffisante pour préférer déléguer celle-ci au <em>transpiler</em> d&#8217;origine au lieu d&#8217;essayer de se la farcir au sein de ST…</p>

<p><strong>SublimeLinter</strong> (<a href="https://github.com/SublimeLinter/SublimeLinter">détails</a>) — <strong>indispensable !</strong></p>

<p>Attention tuerie !  La pratique du <em>linting</em> s&#8217;est bien répandue depuis <a href="http://www.jslint.com/">JSLint</a> et <a href="http://www.jshint.com/">JSHint</a>, mais elle est en fait possible sur la majorité des syntaxes.  Au minimum, la plupart des compilateurs et interpréteurs vous permettent de juste indiquer des erreurs syntaxiques dans leur langage.  Au mieux, vous disposez d&#8217;outils d&#8217;analyse statique de code capables de détecter des <em>code smells</em> tels qu&#8217;une variable inutilisée, un fragment de code jamais exécuté, une syntaxe connue comme problématique sur les vieux IE, un sélecteur CSS trop long ou verbeux pour être honnête…</p>

<p>Ce paquet fournit un mécanisme universel de <em>linting</em> qui recourt ensuite aux outils appropriés en fonction de la syntaxe du buffer en cours.  Je l&#8217;utilise notamment pour Ruby, JavaScript, CoffeeScript et CSS.  Il est vraiment très pratique.</p>

<p>Le <em>linting</em> peut être fait en direct (dès qu&#8217;un délai d&#8217;inactivité, par défaut 2 secondes, a été détecté), automatiquement au chargement et/ou à la sauvegarde, ou manuellement.  On peut régler les outils à utiliser en interne (notamment JSLint ou JSHint) et leurs options par défaut.  Je vous encourage à utiliser <em>au minimum</em> le mode chargement+sauvegarde, et idéalement le mode « live » (sur délai d&#8217;inactivité) : si le <em>linting</em> n&#8217;est pas automatique, vous n&#8217;aurez pas le réflexe de l&#8217;appliquer systématiquement.</p>

<p><strong>TransposeCharacter</strong> (<a href="https://github.com/colinta/SublimeTransposeCharacter">détails</a>)</p>

<p>Il est surprenant que ST n&#8217;ait pas de base une commande de transposition, au moins des caractères autour du curseur.  La dyslexie légère à la frappe, qui résulte de l&#8217;inversion de deux caractères, est si fréquente que la majorité des éditeurs ont une telle commande en natif, généralement calée sur <code>Ctrl+T</code>.  Même la <em>readline</em>, qui contrôle la saisie interactive dans nombre de <em>shells</em>, le fournit.</p>

<p>À quelque chose malheur est bon toutefois : ce paquet va plus loin que la simple transposition de caractères.  Si le curseur est en début ou fin de ligne, il inverse la ligne courante et la précédente/suivante.  En théorie, si une sélection est active, il inverse le côté de la sélection où se trouve le curseur.  Toutefois pour moi, même si ça marche en invocation de commande explicite (<code>Cmd+Shift+P</code>, <code>transpose</code>), ça ne donne rien avec le raccourci clavier…</p>

<p><strong>Unicode Character Highlighter</strong> (<a href="https://github.com/possan/sublime_unicode_nbsp">détails</a>)</p>

<p>Ce paquet permet de mettre automatiquement en lumière (les couleurs sont réglables en triturant le code, ahem…) un certain nombre de caractères Unicode au sein du buffer, par exemple les guillemets français.  Mais ce qui m&#8217;intéresse particulièrement, moi, c&#8217;est qu&#8217;il met en exergue <em><em>les espaces insécables littérales</em> (oui, en typographie, on dit </em>une* espace).</p>

<p>Je suis en effet sur un clavier Mac ou je tape régulièrement et <em>volontairement</em> de telles espaces (<code>Alt+Espace</code>), car j&#8217;aime avoir le strict minimum d&#8217;entités HTML dans mes documents à destination du web (et je ne vous parle pas de tous les cas où je tape un signe double en français dans un contexte qui n&#8217;insère pas une telle espace avant automatiquement).  Mais il y a des cas où ça arrive <em>sans que je le veuille</em>.  Généralement parce que je viens de taper, ou je m&#8217;apprête à taper, un caractère reposant aussi sur <code>Alt</code>, à côté d&#8217;une espace normale.  Et j&#8217;enfonce <code>Alt</code> trop tôt, ou je le relâche trop tard.</p>

<p>Prenez par exemple le code Ruby suivant :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">customer</span> <span class="o">=</span> <span class="n">current_customer</span>
</span><span class='line'><span class="n">customer</span> <span class="o">||=</span> <span class="no">Customer</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="n">customer</span><span class="o">.</span><span class="n">mark_session!</span>
</span></code></pre></td></tr></table></div></figure>


<p>Sur un clavier Mac, pour obtenir un <em>pipe</em> (<code>|</code>), je dois faire <code>Alt+Shift+L</code>.  Dans la section de code <code>customer ||= Cus…</code>, il existe un vrai risque à la frappe que je ponde par inadvertance une espace insécable entre <code>customer</code> et <code>||=</code>, en enfonçant <code>Alt</code> une fraction de seconde trop tôt.  L&#8217;éditeur ne me le signalera pas, et <em>le code reste valide</em>, ce qui fait qu&#8217;à la ligne suivante, la variable <code>customer</code> n&#8217;est en fait pas définie, alors qu&#8217;apparemment la ligne centrale lui a garanti une valeur !  En réalité cette ligne centrale fournit une valeur à la variable <code>customer </code> (le dernier caractère de l&#8217;identifiant est l&#8217;espace insécable).</p>

<p>Je me suis fait mordre par ce type de problème assez de fois pour vouloir voir les espaces insécables immédiatement dans mon code, et bien mises en avant.  D&#8217;où ce paquet.</p>

<h3>Le thème Tomorrow</h3>

<p>ST a une gestion assez fine des thèmes, c&#8217;est-à-dire des palettes de couleur employées pour afficher les buffers.  Tous les thèmes TextMate sont naturellement exploitables, et pendant longtemps j&#8217;utilisais Blackboard pour moi et LAZY pour la vidéo-projection.</p>

<p>Et puis j&#8217;ai découvert <a href="https://github.com/chriskempson/tomorrow-theme#tomorrow-theme">Tomorrow</a>.</p>

<p><img class="left" src="https://raw.github.com/ChrisKempson/Tomorrow-Theme/master/Images/Tomorrow.png" width="337" height="452" title="Le thème Tomorrow par défaut" >
<img class="right" src="https://raw.github.com/ChrisKempson/Tomorrow-Theme/master/Images/Tomorrow-Night-Bright.png" width="337" height="452" title="Le thème Tomorrow en variante Night Bright" ></p>

<div style="clear:both"></div>


<p>Non seulement il fournit des variantes bien adaptées à mes besoins (j&#8217;utilise la variante Night-Bright pour moi et le thème de base pour la vidéo-projection), mais surtout il découpe le code plus finement que la majorité des thèmes ; il différencie davantage de choses.  Et l&#8217;équilibre colorimétrique est vraiment pas mal.  On sent que son créateur, Chris Kempson, est un spécialiste des thèmes et a passé une tonne de temps sur Tomorrow, qui est d&#8217;ailleurs immensément populaire.  Je l&#8217;ai même mis en place au sein de mes slides en <a href="http://lab.hakim.se/reveal-js/">RevealJS</a>, pour mes formations <a href="http://www.js-attitude.fr/tout-sur-les-ateliers/">JS Attitude</a> (il y a des feuilles de style Tomorrow dans <a href="http://softwaremaniacs.org/soft/highlight/en/">Highlight.js</a>).</p>

<h2>Ressources supplémentaires à regarder absolument</h2>

<p>On trouve pléthore d&#8217;articles et séries d&#8217;astuces sur le web autour de ST.  La plupart se répètent…  Mais voici deux ressources que je trouve indispensables :</p>

<ul>
<li>L&#8217;excellent <strong>screencast gratuit</strong> chez NetTuts+ : <a href="https://tutsplus.com/course/improve-workflow-in-sublime-text-2/">Perfect Workflow in Sublime Text 2</a>.  Bien structuré et découpé pour un accès ciblé facile, plus de 3h de screencast qualitatif, avec une tonne métrique de manips utiles pour être bien opérationnels tout de suite !</li>
<li>Le screencast de Mike Riley téléchargeable chez Pragmatic Programmers : <a href="http://pragprog.com/screencasts/v-mrst2/sublime-text-2">Sublime Text 2</a>.  54 minutes, seulement $12, dispo en une pléthore de formats.</li>
</ul>


<p>Allez à présent, et éditez dans la joie !</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Les sessions jusqu'à fin juin 2013 sont là !]]></title>
    <link href="http://www.js-attitude.fr/2013/03/12/sessions-q2-2013/"/>
    <updated>2013-03-12T15:45:00+01:00</updated>
    <id>http://www.js-attitude.fr/2013/03/12/sessions-q2-2013</id>
    <content type="html"><![CDATA[<p>Nous venons de poser les dates des sessions de mai et juin 2013.  Voici le récap complet des sessions à venir :</p>

<ul>
<li><a href="http://www.js-attitude.fr/js-total/">JS Total</a> du 9 au 12/04 (attention, il ne reste presque plus de places)</li>
<li><a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a> le 23/04.  Jetez-vous dessus, ça déchire !</li>
<li><a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> le 30/04</li>
<li><a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> le 21/05</li>
<li><a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a> le 19/06</li>
<li><a href="http://www.js-attitude.fr/js-total/">JS Total</a> du 25 au 28/06</li>
</ul>


<p>Comme toujours, vous pouvez <a href="http://www.js-attitude.fr/demander-une-convention/">demander une convention</a> pour une session inter-entreprises (remplissez bien tous les champs), ou nous contacter pour un besoin <a href="http://www.js-attitude.fr/demander-une-intra-ou-custom/">intra-entreprise ou sur mesure</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sessions à venir et promotions]]></title>
    <link href="http://www.js-attitude.fr/2013/03/08/sessions-a-venir-et-promotions/"/>
    <updated>2013-03-08T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2013/03/08/sessions-a-venir-et-promotions</id>
    <content type="html"><![CDATA[<p>Ayé, le premier mars est passé, vous êtes censés avoir cotisé à vos OPCA et tout et tout, c&#8217;est le moment de profiter des formations 2013 !</p>

<p>Pour rappel, les sessions suivantes arrivent :</p>

<ul>
<li><strong>9–12 avril</strong> : c&#8217;est la prochaine <a href="http://www.js-attitude.fr/js-total/">JS Total</a>, et comme d&#8217;habitude elle est déjà presque pleine un mois à l&#8217;avance.  C&#8217;est notre <em>blockbuster</em> et ça n&#8217;a rien d&#8217;étonnant, vu son programme alléchant.  Dépêchez-vous de rafler les dernières places libres, sinon vous devrez attendre juin !</li>
<li><strong>23 avril</strong> verra la première session <a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a>, attendue de longue date, qui va mettre elle aussi des étoiles plein les yeux des participants…</li>
</ul>


<p>Côté <a href="http://www.git-attitude.fr/">Git</a>, la session <a href="http://www.git-attitude.fr/git-au-quotidien/">Git au Quotidien</a> du 26 mars est déjà pleine, mais il reste des places pour l&#8217;excellente <a href="http://www.git-attitude.fr/git-avance/">Git Avancé</a> qui suivra le <strong>27 mars</strong>.</p>

<p>Nous annoncerons d&#8217;ici une à deux semaines les dates des sessions inter-entreprises pour mai (il y en aura peu, le mois est déjà chargé pour nous) et juin 2013.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[10 bonnes pratiques JavaScript]]></title>
    <link href="http://www.js-attitude.fr/2013/01/21/dix-bonnes-pratiques-javascript/"/>
    <updated>2013-01-21T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2013/01/21/dix-bonnes-pratiques-javascript</id>
    <content type="html"><![CDATA[<p>Au fil des formations, je remarque que de nombreuses bonnes pratiques que je signale en passant dans le code, par acquis de conscience, ne sont pas connues, ou pas comprises, ou juste surprenantes pour les stagiaires.  C&#8217;est l&#8217;occasion de me souvenir que dans tous les domaines, ce qui peut paraître évident et « connu de tous » ne l&#8217;est pas forcément, et qu&#8217;il est toujours bon de remettre en lumière des savoirs dont on imagine, souvent à tort, qu&#8217;ils sont monnaie courante.</p>

<p>Voici donc dix bonnes pratiques choisies parmi un large ensemble de candidates ; vous en connaîtrez sûrement certaines, mais probablement pas toutes.  Je pensais qu&#8217;il en faudrait 10 pour faire un article un peu consistant, et au final c&#8217;est un mammouth qui aurait pu être découpé en plusieurs articles histoire de faire durer le plaisir…  Mais je suis d&#8217;humeur généreuse et j&#8217;ai encore plein d&#8217;articles sous le coude, alors je vous livre tout ça d&#8217;un coup :-)</p>

<p>N&#8217;hésitez pas à faire vos retours en commentaires !</p>

<!-- more -->


<h2>1. Court-circuiter les blocs plutôt que les imbriquer</h2>

<p>Court-circuiter le code, en JavaScript, c&#8217;est recourir à <code>return</code>, <code>break</code> ou <code>continue</code> pour sauter tout ou partie du contexte en cours (fonction ou boucle), et s&#8217;épargner ainsi des blocs imbriqués inutiles, avec ce que ça suppose d&#8217;indentation supplémentaire…</p>

<p>Il est certes primordial de bien indenter son code, quel que soit le langage.  Dès qu&#8217;on ne se limite pas à un code trivial de 2-3 lignes, visualiser les dépendances logiques des conditions, boucles et fonctions devient impératif.</p>

<p>Toutefois, il est dommage d&#8217;indenter inutilement.  Trop d&#8217;indentations imbriquées crée souvent un <em>a priori</em> négatif sur le code en donnant une vision faussée de sa complexité.  Cela rend aussi le code moins lisible et facile à appréhender.</p>

<p>Voyons quelques exemples.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">processItems</span><span class="p">(</span><span class="nx">list</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">[];</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">normalize</span><span class="p">(</span><span class="nx">items</span><span class="p">);</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="c1">// code bien long…</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ici il est dommage d&#8217;avoir deux niveaux.  Le cœur de code étant dans un <code>if</code>, il suffit de tester la condition inverse et de court-circuiter avec un <code>return</code> :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">processItems</span><span class="p">(</span><span class="nx">list</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">[];</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">normalize</span><span class="p">(</span><span class="nx">items</span><span class="p">);</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// code bien long…</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Le même principe peut s&#8217;appliquer dans les boucles, en utilisant suivant les cas <code>continue</code> ou <code>break</code>.  Ainsi, le code suivant :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">while</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">item</span> <span class="o">=</span> <span class="nx">items</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="s1">&#39;taggable&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// code bien long…</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>…deviendrait celui-ci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">while</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">item</span> <span class="o">=</span> <span class="nx">items</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">item</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="s1">&#39;taggable&#39;</span><span class="p">))</span>
</span><span class='line'>    <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// code bien long…</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Au passage, vous ne le savez peut-être pas mais <code>break</code> et <code>continue</code> autorisent le recours à un <em>label</em> pour court-circuiter au-delà de leur boucle conteneur immédiate, et remonter ainsi de plusieurs niveaux (mais toujours au sein de la fonction courante).  Voici un exemple de recherche dans une matrice, hors la diagonale.  On ignore la diagonale en court-circuitant le tour courant avec un <code>continue</code> simple, mais si on trouve la valeur recherchée, on court-circuite l&#8217;ensemble des boucles pour aller directement à la suite de la fonction, au moyen d&#8217;un label sur la boucle externe et de son emploi dans le <code>break</code> interne :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">searchGridExceptDiagonal</span><span class="p">(</span><span class="nx">grid</span><span class="p">,</span> <span class="nx">cell</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">outer</span><span class="o">:</span> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">rowIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">rows</span> <span class="o">=</span> <span class="nx">grid</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">rowIndex</span> <span class="o">&lt;</span> <span class="nx">rows</span><span class="p">;</span> <span class="o">++</span><span class="nx">rowIndex</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">colIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">cols</span> <span class="o">=</span> <span class="nx">grid</span><span class="p">[</span><span class="nx">colIndex</span><span class="p">].</span><span class="nx">length</span><span class="p">;</span> <span class="nx">colIndex</span> <span class="o">&lt;</span> <span class="nx">cols</span><span class="p">;</span> <span class="o">++</span><span class="nx">colIndex</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">rowIndex</span><span class="p">,</span> <span class="nx">colIndex</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nx">rowIndex</span> <span class="o">==</span> <span class="nx">colIndex</span><span class="p">)</span>
</span><span class='line'>        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nx">cell</span> <span class="o">===</span> <span class="nx">grid</span><span class="p">[</span><span class="nx">rowIndex</span><span class="p">][</span><span class="nx">colIndex</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">result</span> <span class="o">=</span> <span class="p">[</span><span class="nx">rowIndex</span><span class="p">,</span> <span class="nx">colIndex</span><span class="p">];</span>
</span><span class='line'>        <span class="k">break</span> <span class="nx">outer</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nx">processResult</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Enfin, il existe le fameux cas du « <code>return else</code> », un cas classique de superflu.  Voyez plutôt :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">processItems</span><span class="p">(</span><span class="nx">items</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">[];</span>
</span><span class='line'>  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">[];</span>
</span><span class='line'>    <span class="c1">// code bien long…</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>C&#8217;est parfaitement superflu, comme en atteste l&#8217;exemple plus haut : un <code>return</code> court-circuite la fonction conteneur, le <code>else</code> est donc sans intérêt : on peut utiliser directement le code qu&#8217;il contient.</p>

<p>Bref : l&#8217;indentation c&#8217;est bien, mais en faire trop c&#8217;est moins bien !  N&#8217;abusons pas des bonnes choses…</p>

<h2>2. Comparer avec les <em>rvalues</em> à gauche</h2>

<p>Qu’est-ce qu’une <em>rvalue</em> ?  En jargon d&#8217;analyse syntaxique (<em>parsing</em>), on désigne ainsi l&#8217;opérande droit d&#8217;un opérateur.  Par symétrie, l&#8217;opérande gauche est appelé <em>lvalue</em>.  Par exemple, dans <code>x == 42</code>, <code>x</code> est la <em>lvalue</em> et <code>42</code> la rvalue.  Dans <code>str += 3</code>, ce seraient évidemment <code>str</code> et <code>3</code>, respectivement.</p>

<p>Dans tous les langages où l&#8217;opérateur d&#8217;affectation (<code>=</code>) est un sous-ensemble de celui de comparaison (<code>==</code>), et où l&#8217;affectation est une expression, on risque de tomber dans le piège du <em>égale manquant</em>.  Ainsi en JavaScript C, C++, Java, Ruby, etc. on peut se gaufrer comme suit :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">list</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">list</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="mi">42</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// code de traitement…</span>
</span><span class='line'>  <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Vous avez vu la blague ?  Le <code>=</code> au lieu du <code>==</code> ?  C&#8217;est un piège fréquent même pour les développeurs chevronnés : après tout, c&#8217;est « juste »  une faute de frappe.  Mais c&#8217;est tellement discret que ça peut être infernal à déboguer.</p>

<p>Si vous avez un bon outillage associé à votre éditeur de code, votre compilateur ou votre interpréteur, il vous fera probablement remarquer qu&#8217;il y a ici baleine sous gravier.  C&#8217;est par exemple le cas de <a href="http://www.jslint.com/">JSLint</a> et <a href="http://www.jshint.com/">JSHint</a>, tous deux fournis par exemple dans Sublime Text 2 au moyen de l&#8217;excellent plugin <a href="https://github.com/SublimeLinter/SublimeLinter">SublimeLinter</a>.</p>

<p>Vous avez alors le choix :</p>

<ul>
<li>soit il s&#8217;agit bien d&#8217;une affectation à la volée (pour utilisation de la valeur dans le bloc, par exemple), et vous pouvez rendre ça explicite en <em>doublant les parenthèses</em> ;</li>
<li>soit c&#8217;est une comparaison et vous rajoutez un <code>=</code>.</li>
</ul>


<p>Toutefois, le souci principal c&#8217;est que ça puisse arriver (ce code s&#8217;exécute, il est valide ; il fait juste n&#8217;importe quoi…) alors que vous visiez une comparaison.  C&#8217;est pourquoi dans tous ces langages j&#8217;ai le réflexe d&#8217;inverser, pour les comparaisons d&#8217;égalité uniquement (<code>==</code> et <code>===</code>, en JavaScript), la <em>lvalue</em> et la <em>rvalue</em>.  Ça donnerait ceci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">list</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="mi">42</span> <span class="o">==</span> <span class="nx">list</span><span class="p">[</span><span class="nx">index</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// code de traitement…</span>
</span><span class='line'>  <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Voyez-vous ce qui se passe ?  Si j&#8217;oublie un <code>=</code>, l&#8217;affectation résultante n&#8217;est pas valide : je ne peux pas modifier le litéral de gauche…  Bien sûr, si je compare deux variables ou autres opérandes modifiables, ça ne m&#8217;aide pas.  Et si j&#8217;opte normalement pour des égalités strictes (<code>===</code>), le risque de n&#8217;avoir qu&#8217;un <code>=</code> est bien moindre.  Mais au global, c&#8217;est une habitude qui a sauvé un nombre incalculable de fois mes étudiants, stagiaires, collègues…  et moi-même, naturellement.</p>

<h2>3. Mettre en cache les expressions lourdes</h2>

<p>Il existe de nombreux cas où une expression JS, aussi courte soit-elle, est lourde à exécuter.</p>

<p>Certaines sont intuitivement lourdes, comme le <code>$(selector)</code> de jQuery (ce qui n&#8217;empêche pas les gens de faire quinze fois la même sélection dans leur fonction…) ou un appel à une de vos fonctions dont vous savez qu&#8217;elle mouline pas mal.</p>

<p>D&#8217;autres sont plus subtiles ou surprenantes, comme les litéraux d&#8217;<a href="http://www.js-attitude.fr/2012/08/13/enfin-maitriser-les-expressions-rationnelles/">expressions rationnelles</a> ou les longueurs de tableaux.</p>

<p>Mettre en cache, ou si vous préférez <em>memoizing</em> ces expressions peut avoir une influence notable sur vos performances dans un code utilisé intensivement.</p>

<p>Commençons par les cas évidents :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// BEUARK :</span>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#foo .bar&#39;</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="nx">handleBarClick</span><span class="p">);</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">escapesToo</span><span class="p">)</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#foo .bar&#39;</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;keypress&#39;</span><span class="p">,</span> <span class="nx">handleEscapes</span><span class="p">);</span>
</span><span class='line'><span class="nx">items</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#foo .bar&#39;</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="nx">item</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ce type de code est plus fréquent qu&#8217;on ne croie, tant les développeurs préfèrent copier-coller que refactoriser leur code, aussi simple cela soit-il ici.  Naturellement, conserver l&#8217;objet jQuery résultat est une bien <a href="http://jsperf.com/caching-jquery-selectors">meilleure</a> <a href="http://jsperf.com/caching-jquery-objects-perf/13">option</a> (ou recourir au chaînage, quand c&#8217;est possible) :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">scope</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#foo .bar&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nx">scope</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="nx">handleBarClick</span><span class="p">);</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">escapesToo</span><span class="p">)</span>
</span><span class='line'>  <span class="nx">scope</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;keypress&#39;</span><span class="p">,</span> <span class="nx">handleEscapes</span><span class="p">);</span>
</span><span class='line'><span class="nx">items</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">scope</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nx">item</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Lorsque vous réalisez une fonction dont le résultat n&#8217;est pas censé changer pour une même série d&#8217;arguments, mais qui est susceptible d&#8217;être souvent appelée, il est souhaitable de recourir à la <em>memoization</em> pour cette fonction.  Voyons un cas simple, sans arguments :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">heavyDuty</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="kc">undefined</span> <span class="o">!==</span> <span class="nx">heavyDuty</span><span class="p">.</span><span class="nx">cached</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">heavyDuty</span><span class="p">.</span><span class="nx">cached</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// Gros code bien lourd et compliqué, voire coûteux financièrement (appels API, toussa…)</span>
</span><span class='line'>  <span class="nx">heavyDuty</span><span class="p">.</span><span class="nx">cached</span> <span class="o">=</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Si ça dépend des arguments, <code>cached</code> peut devenir un hash (<code>{}</code>) dont les clés sont des <code>String</code> construites sur base des arguments.  On peut même génériser tout ça facilement et en faire un mixin.  La bibliothèque <a href="http://underscorejs.org/">Underscore</a>, parmi ses myriades de fonctions cool, propose ainsi <a href="http://underscorejs.org/#memoize"><code>_.memoize</code></a> à cet effet.</p>

<p>Plus subtil à présent : les expressions rationnelles.</p>

<p>Lorsqu&#8217;on recourt à une regex assez courte, il est fréquent de se contenter de la copier-coller, ou simplement de la laisser litérale au sein d&#8217;un boucle par exemple.  C&#8217;est dommage, car alors on risque de la voir « compiler » à chaque utilisation, donc à chaque tour de boucle :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// SAYMAL :</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">longArray</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">line</span> <span class="o">=</span> <span class="nx">longArray</span><span class="p">[</span><span class="nx">index</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="sr">/[\s\u00a0][:;?!]/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">line</span><span class="p">))</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">line</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Il est <a href="http://jsperf.com/putting-regexes-out-of-loops">préférable</a> de sortir la regex de la boucle, voire de la fonction et d&#8217;en faire une « constante » (en ES3, on n&#8217;a pas <code>const</code>, on utilisera donc <code>var</code>) :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">WHITESPACE_AND_DOUBLE_SIGN</span> <span class="o">=</span> <span class="sr">/[\s\u00a0][:;?!]/</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">longArray</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">line</span> <span class="o">=</span> <span class="nx">longArray</span><span class="p">[</span><span class="nx">index</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">WHITESPACE_AND_DOUBLE_SIGN</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">line</span><span class="p">))</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">line</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Cela a en outre le double avantage d&#8217;expliciter le sens de la regex et de faciliter la vie à certaines colorations syntaxiques :-)</p>

<p>Notez au passage une autre bonne pratique conjointe : lorsqu&#8217;on veut juste un résultat booléen sur la regex (correspondance ou non), sans s&#8217;intéresser au détail de la correspondance, on utilisera avec profit <code>regex.test(string)</code> plutôt que <code>string.match(regex)</code>.  La première est <a href="http://jsperf.com/regexp-test-vs-match-m5">nettement plus performante</a> que la seconde, car elle renvoie juste un booléen et ne s&#8217;occupe pas de constituer des groupes, etc.</p>

<p>Dernier cas évoqué ici : les longueurs de tableaux.</p>

<p>Il est vain de vouloir deviner comment votre <em>runtime</em> JS représente en interne votre <code>Array</code> JavaScript.  Cela dépend de la runtime, des types de valeur stockées et de la longueur du tableau.  Suivant les cas, il peut s&#8217;agir d&#8217;un véritable tableau (zone de mémoire continue à indexation directe), d&#8217;une liste liée, voire d&#8217;une structure plus avancée.</p>

<p>En conséquence, il n&#8217;est pas rare (surtout sur les vieux navigateurs) que le code en apparence bénin <code>myArray.length</code> soit en réalité coûteux, exigeant en interne le parcours intégral du tableau.  Une boucle « classique » sur la longueur aurait donc une <a href="http://fr.wikipedia.org/wiki/Th%C3%A9orie_de_la_complexit%C3%A9_%28informatique_th%C3%A9orique%29#Complexit.C3.A9_en_temps_et_en_espace">complexité quadratique</a> :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// RISKY</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">myArray</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span>
</span><span class='line'>  <span class="c1">// …</span>
</span></code></pre></td></tr></table></div></figure>


<p>Dans la mesure où les boucles sur des tableaux dont la longueur change au fil des tours sont rarissimes (et sources de bien des bugs), il est toujours préférable de mettre la longueur (fixe) « en cache » dans une variable, au sein de la section d&#8217;initialisation de la boucle :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">myArray</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span>
</span><span class='line'>  <span class="c1">// …</span>
</span></code></pre></td></tr></table></div></figure>


<p>Naturellement, si vous passez par un itérateur (ceux d&#8217;ES5 : <code>forEach</code>, <code>map</code>, <code>some</code>… ou ceux d&#8217;Underscore, de jQuery, etc.) vous pouvez leur faire confiance pour avoir fait au mieux.</p>

<h2>4. Utiliser la délégation d&#8217;événements plutôt que des tas de gestionnaires étroits</h2>

<p>On est là aussi dans les trucs rabâchés depuis bien 5 ans, mais je vois toujours plein de gens qui font le contraire, alors revenons-y.</p>

<p>Dans une page web, vous associez des gestionnaires d&#8217;événements (<em>event handlers</em>) à des événements sur divers endroits de la page.  Le réflexe initial consiste à les associer « au plus près », sur l&#8217;élément lui-même en général.</p>

<p>La plupart du temps, ça ne pose aucun souci, c&#8217;est même une bonne idée.</p>

<p>Mais il y a au moins deux situations dans lesquelles c&#8217;est soit super lourd, soit carrément cassé.</p>

<p>Le premier cas, c&#8217;est lorsque vous écoutez le même événement sur pléthore d&#8217;éléments.  Par exemple, tous les éléments d&#8217;une liste ; toutes les lignes d&#8217;un corps de tableau ; tous les liens porteurs d&#8217;une classe CSS donnée…  Attacher un gestionnaire par élément, alors que le comportement est partagé, est inutilement lourd et peut vite <a href="http://jsperf.com/jquery-event-delegation/5">dégrader les performances</a> quand le nombre d&#8217;éléments est élevé.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Un gestionnaire par élément (beuark) :</span>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;ul#files li&#39;</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">item</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'>  <span class="c1">// …</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>On préfère alors tirer parti du <em>bubbling</em> (le fait que les événements « bouillonnent » au travers du DOM, d&#8217;un élément vers son parent et ainsi de suite jusqu&#8217;au document) et attacher le gestionnaire au plus proche commun parent (souvent le document, mais ça peut être bien plus ciblé, comme la liste qui contient tous les éléments souhaités).  On aura alors recours à une syntaxe de capture appropriée.  Par exemple :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Un gestionnaire délégué pour tous les éléments :</span>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;ul#files&#39;</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="s1">&#39;li&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">item</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'>  <span class="c1">// …</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>(Dans les deux cas avec jQuery, <code>this</code> fera bien référence au <code>&lt;li&gt;</code>.)</p>

<p>L&#8217;autre cas de figure où une connexion trop ciblée des gestionnaires d&#8217;événement est problématique concerne le chargement/remplacement de contenus HTML (le plus souvent <em>via</em> Ajax).  Si on attache ces gestionnaires sur une zone de la page qui va se faire remplacer par la suite (au moyen d&#8217;un appel manuel à <code>.html(…)</code> ou <code>$.load(…)</code>, par exemple), ces gestionnaires resteront attachés aux anciens éléments désormais disparus, alors que les nouveaux éléments fraîchement injectés ne disposeront pas, eux, de gestionnaires d&#8217;événements.</p>

<p>Il est alors préférable de déléguer ces gestionnaires au niveau du conteneur de la zone qui va évoluer (être remplacée/rechargée).  jQuery assurant le bouillonnement même des événements qui, sur les vieux IE, ne bouillonnent pas (<code>focus</code>, <code>blur</code>, <code>change</code> et <code>submit</code>), cette solution est exploitable pour tous les événements voulus.  Ainsi, nul besoin de les rattacher le moment venu, ou de nettoyer ceux installés avant le remplacement du contenu.</p>

<h2>5. Isoler son code avec le <em>module pattern</em></h2>

<p>Encore aujourd&#8217;hui, en 2013, l&#8217;immense majorité des développeurs JS côté navigateur pondent leur code <em>au niveau global</em>.  Imaginons qu&#8217;on vous demande de notifier Google Analytics de tout téléchargement de fichier sur votre site, sachant que vous avez pris soin de coller une classe CSS <code>file</code> aux liens correspondants.  Vous pourriez ajouter à votre page un script <code>track_downloads.js</code> qui ressemblerait à ceci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">trackLink</span><span class="p">(</span><span class="nx">link</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">_gaq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;_trackEvent&#39;</span><span class="p">,</span> <span class="s1">&#39;files&#39;</span><span class="p">,</span> <span class="s1">&#39;download&#39;</span><span class="p">,</span> <span class="nx">link</span><span class="p">.</span><span class="nx">href</span><span class="p">]);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="s1">&#39;a.file&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">trackLink</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>C&#8217;est un cas <em>light</em>, parce qu&#8217;en vérité, vos fichiers sont souvent multi-sujets, ou en tout cas « pourrissent le global » avec des tas de fonctions et variables partagées… (Si si, avouez, ça vous arrive, je le sais, je le vois tout le temps).</p>

<p>Outre que ça pose souci le jour où vous utilisez un autre morceau de code qui lui aussi aurait une fonction globale <code>trackLink</code> (collision de noms : le dernier qui a parlé a raison), c&#8217;est juste dommage de polluer ainsi la portée globale <em>pour rien</em>.  En effet, la majorité de vos codes sont en fait autonomes, ou comme disent les anglais <em>self-contained</em> : ils n&#8217;ont pas d&#8217;API publique à fournir, ils ont juste du code interne à leur fonctionnement, attaché à la page par gestionnaires d&#8217;événements.</p>

<p>Il est dès lors préférable d&#8217;enrober votre fichier dans un module.  Je ne parle pas forcément d&#8217;un « vrai » module (au sens <a href="http://requirejs.org/docs/whyamd.html">AMD</a> ou <a href="http://wiki.commonjs.org/wiki/Modules/1.1">CommonJS</a>, par exemple), mais au minimum du <em>module pattern</em>, qui est au cœur des autres et repose simplement sur une fonction immédiatement exécutée (<em>Immediately-Invoked Function Expression</em>, ou IIFE, en anglais) :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">$</span><span class="p">,</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">function</span> <span class="nx">trackLink</span><span class="p">(</span><span class="nx">link</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">_gaq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;_trackEvent&#39;</span><span class="p">,</span> <span class="s1">&#39;files&#39;</span><span class="p">,</span> <span class="s1">&#39;download&#39;</span><span class="p">,</span> <span class="nx">link</span><span class="p">.</span><span class="nx">href</span><span class="p">]);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="s1">&#39;a.file&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">trackLink</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="p">})(</span><span class="nx">jQuery</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ici tout le code définit en fait une fonction anonyme, qu&#8217;il appelle immédiatement.  En vertu des règles de portée et de <em>closure</em> de JavaScript, les déclarations de fonction et les <code>var</code> à l&#8217;intérieur d&#8217;une fonction lui sont privées : l&#8217;extérieur ne sait donc rien, par exemple, de <code>trackLink</code>.</p>

<p>J&#8217;utilise ici au passage des petites astuces habituelles quant aux arguments de l&#8217;IIFE (elle peut très bien ne pas en avoir) :</p>

<ul>
<li>Au cas où jQuery serait utilisé en <a href="http://api.jquery.com/jQuery.noConflict/">mode noConflict</a>, je me permets tout de même d&#8217;y référer facilement avec <code>$</code> grâce à un argument dédié.</li>
<li>Si jamais un petit malin a pourri <code>undefined</code> en collant par exemple un <code>undefined = 42;</code> quelque part, ça ne m&#8217;atteint pas car grâce à mon deuxième paramètre qui n&#8217;aura pas d&#8217;argument correspondant, dans mon « module », <code>undefined</code> est bien <code>undefined</code> (bon, ici on ne s&#8217;en sert pas, mais c&#8217;est un schéma désormais classique…).</li>
</ul>


<p>Si le sujet des <em>module patterns</em> et toutes les variations/évolutions possibles vous intéressent, <a href="http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth">cet article déjà ancien</a> de Ben Cherry, développeur front-end chez Twitter, est une excellente lecture.</p>

<h2>6. Découpler son code grâce aux événements personnalisés</h2>

<p>Le saviez-tu ?  Ce n&#8217;est pas parce que du code externe a besoin de déclencher du code à toi que tu dois nécessairement en faire une API publique (c&#8217;est-à-dire des fonctions accessibles de l&#8217;extérieur).  En fait, il existe notamment un cas de figure où une fonction publique n&#8217;est pas la bonne solution : la maintenance opérationnelle suite à un événement extérieur.</p>

<p>« Gni ? »</p>

<p>Imaginons que tu codes un module qui décore tout champ de type date avec un joli widget à toi (comment ça, tu n&#8217;utilises pas <a href="https://github.com/ChiperSoft/Kalendae">Kalendae</a> ?!).  Tu as respecté les préceptes du point précédent (module opaque décorant automatiquement les <code>input[type=date], input.date</code> au chargement du DOM, par exemple), mais tu te retrouves soudain confronté à un problème : si quelqu&#8217;un met à jour la page plus tard (avec Ajax ou un système de templates…) les nouveaux champs ne seront pas décorés.</p>

<p>Ni une ni deux, tu « exportes » donc une méthode publique, probablement collée en global au niveau de <code>window</code> ou d&#8217;un espace de noms dédié à ton module ; une méthode du genre <code>refreshDatePickers()</code>.  Peut-être que ton code ressemble à ça, exploitant ce que Ben Cherry appelle la <em>loose augmentation</em> :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">TotoWidgets</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">exports</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// ton joli code bien planqué ici…</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">function</span> <span class="nx">refreshDatePickers</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// …</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// ton init ici…</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">exports</span><span class="p">.</span><span class="nx">refreshDatePickers</span> <span class="o">=</span> <span class="nx">refreshDatePickers</span><span class="p">;</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">exports</span><span class="p">;</span>
</span><span class='line'><span class="p">})(</span><span class="nx">TotoWidgets</span> <span class="o">||</span> <span class="p">{});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Mais c&#8217;est dommage.  On est ici dans le cas typique où :</p>

<ul>
<li>ta méthode ne renvoie rien</li>
<li>elle est en fait, conceptuellement, un gestionnaire d&#8217;événement… pour un événement « un morceau de la page a changé » qui n&#8217;existe pas (ou pas forcément)</li>
</ul>


<p>Une solution plus discrète (dans le sens où elle ne te force pas à publier quelque API que ce soit) consisterait à utiliser un <em>événement personnalisé</em>, que tu déclencherais par exemple au niveau de la zone qui a changé (avec un bête <code>.trigger</code>), et que ton module écouterait au niveau document.  Ça donnerait quelque chose comme ça :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Dans ton module de widget :</span>
</span><span class='line'><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">knownWidgets</span> <span class="o">=</span> <span class="p">{};</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">function</span> <span class="nx">initWidgets</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">zone</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span> <span class="o">||</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">zone</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="s1">&#39;input[type=date], input.date&#39;</span><span class="p">).</span><span class="nx">each</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">element</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">element</span><span class="p">.</span><span class="nx">id</span> <span class="o">||</span> <span class="nx">_</span><span class="p">.</span><span class="nx">uniqueId</span><span class="p">(</span><span class="s1">&#39;datePicker&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nx">knownWidgets</span><span class="p">[</span><span class="nx">element</span><span class="p">.</span><span class="nx">id</span><span class="p">])</span>
</span><span class='line'>        <span class="k">return</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>      <span class="nx">knownWidgets</span><span class="p">[</span><span class="nx">element</span><span class="p">.</span><span class="nx">id</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MyDatePickerWidget</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">initWidgets</span><span class="p">();</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;pageupdate.ui&#39;</span><span class="p">,</span> <span class="nx">initWidgets</span><span class="p">);</span>
</span><span class='line'><span class="p">})();</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="c1">// Dans le code qui modifie un morceau de la page (ex. Ajax) :</span>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;ul#files&#39;</span><span class="p">).</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;/files&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">&#39;pageupdate.ui&#39;</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Dans l&#8217;idéal, tu « standardises » ces événements custom à travers toute la couche UI de ton code JavaScript, de sorte que ça devient une sorte d&#8217;habitude pour tous tes widgets internes, etc.  En fait, ce n&#8217;est ni plus ni moins que du <a href="http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">publish/subscribe</a> (ou si tu préfères, <a href="http://fr.wikipedia.org/wiki/Observateur_(patron_de_conception">observateur/observé</a>)), mais avec le bouillonnement en plus, et donc la notion de zone DOM concernée.</p>

<h2>7. Proposer un hash d&#8217;options plutôt qu&#8217;une signature à rallonge</h2>

<p>Lorsqu&#8217;on écrit une masse minimum de code (à partir de quelques fonctions, surtout si elles sont publiques), il est toujours bénéfique de réfléchir à l&#8217;<em>API design</em>, c&#8217;est-à-dire à la conception générale de l&#8217;API ainsi produite.  Qui utilisera ce code ? Comment ? Pour quels besoins ? Dans quels contextes ?  Ce type de recul et de mise en perspective est hélas trop rare, même chez les designers d&#8217;API chevronnés, comme en attestent nombre d&#8217;exemples proéminents.  Pour n&#8217;en citer que quelques-uns :</p>

<ul>
<li><code>jQuery.each</code>, le seul itérateur à ma connaissance à coller l&#8217;<em>index</em> en premier plutôt que la valeur, source à lui seul de semaines-hommes entières perdues chaque jour à l&#8217;échelle mondiale…</li>
<li>L&#8217;API XSL/T du JDK ; le cas dominant (90% du besoin) étant l&#8217;application d&#8217;une feuille XSLT sur un document XML, cette situation requiert… une bonne douzaine de lignes de code.</li>
<li>Dans le même esprit, le module <code>Net::HTTP</code> de Ruby.  Prendre en charge HTTPS ou simplement traverser les redirections, deux besoins ultra-basiques, nécessitent quelques lignes de code non trivial.</li>
<li><code>XMLHttpRequest</code> : outre sa casse discutable (XML en majuscules mais Http en casse Camel ?!), le cas de base Ajax nécessite une demi-douzaine de lignes de code, ce qui a immédiatement entraîné nombre de wrappers, au point qu&#8217;aujourd&#8217;hui peut-être un développeur front-end sur mille connait l&#8217;API d&#8217;origine…</li>
<li>Au bas mot la moitié de l&#8217;API standard PHP : entre les paramètres jamais placés dans l&#8217;ordre intuitif, les casses variables, les ordonnancements aléatoires dans les noms de fonctions, etc. c&#8217;est un des plus emblématiques foutoirs du développement contemporain.</li>
</ul>


<p>Bien concevoir une API change radicalement sa facilité de découverte et d&#8217;apprentissage, et le plaisir qu&#8217;on a à l&#8217;employer.  Je ne saurais trop vous conseiller à cet égard l&#8217;excellente conférence de Jake Archibald à Paris Web 2010 : <a href="http://www.dailymotion.com/video/xgmaoy_reusable-code-for-good-or-for-awesome-jake-archibald_tech">Reusable Code: For Good or For Awesome</a>, qui regorge d&#8217;exemples concrets et d&#8217;humour ravageur.</p>

<p>Un des points les plus critiques du design d&#8217;une API reste pour moi la signature des fonctions/méthodes publiques.  En particulier le passage à un hash d&#8217;options au lieu de paramètres positionnés dès lors qu&#8217;on dépasse, disons, 3 paramètres, ou que ceux-ci ont le même type de données attendu.  Ainsi, on obtient un effet similaire aux paramètres nommés dans certains langages, ce qui fait que les <em>appels</em> à la fonction sont en quelque sorte « auto-documentés ».</p>

<p>Personne n&#8217;aime tomber sur du code de ce genre :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">Toolkit</span><span class="p">.</span><span class="nx">initWidgets</span><span class="p">(</span><span class="s1">&#39;container&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nx">bindConnectors</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="s1">&#39;foo&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">,</span> <span class="mi">1000</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Quand on tombe sur ce code, que ce soit celui d&#8217;un autre ou le nôtre il y a 3 mois (ce qui revient au même), on se demande automatiquement « mais ?!  Ça fait quoi ce <code>true</code> ? », et ce pour pratiquement chaque paramètre.</p>

<p>On préfèrerait tous tomber sur ceci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">Toolkit</span><span class="p">.</span><span class="nx">initWidgets</span><span class="p">(</span><span class="s1">&#39;container&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">autoBind</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">hideNative</span><span class="o">:</span> <span class="kc">false</span> <span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="nx">bindConnectors</span><span class="p">({</span> <span class="nx">interval</span><span class="o">:</span> <span class="mi">25</span><span class="p">,</span> <span class="nx">separator</span><span class="o">:</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="nx">container</span><span class="o">:</span> <span class="s1">&#39;foo&#39;</span><span class="p">,</span> <span class="nx">autoRefresh</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">delay</span><span class="o">:</span> <span class="mi">1000</span> <span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Dans le même esprit, ce n&#8217;est pas parce qu&#8217;une fonction propose une trentaine d&#8217;options que je dois <em>me les fader à chaque fois</em>.  De ce point de vue, les fonctionnalités Ajax de jQuery sont un excellent exemple de conception pratique : <code>$.ajax</code> et ses aliases/wrappers, tels <code>$.get</code> ou <code>$(…).load</code>, sont tous conçus avec un hash d&#8217;options et des valeurs par défaut bien adaptées à la majorité des cas.</p>

<p>Mettre en place ce type de fonction ne nécessite pas forcément plus de travail que pour une fonction à la signature plus directe.  Parfois, ça en nécessite même moins.</p>

<p>Avant d&#8217;écrire le code à l&#8217;intérieur d&#8217;une fonction à la signature non triviale, je vous encourage à la documenter immédiatement.  Cash, juste au-dessus de la déclaration, dans un commentaire.  Et surtout, <strong>surtout</strong>, mettez-y des <strong>exemples concrets d&#8217;appels</strong>.  Ce n&#8217;est qu&#8217;en vous forçant ainsi à considérer les choses du point de vue « code appelant » (utilisateur, donc) que vous verrez rapidement si la signature que vous aviez initialement imaginée est adaptée ou doit être repensée.  Et c&#8217;est à ce moment-là, alors qu&#8217;aucune ligne de code n&#8217;a été écrite encore dans la fonction, que le <em>refactoring</em> de la signature n&#8217;a aucun coût supplémentaire.</p>

<p>Ensuite, écrire une telle fonction repose sur quelques principes simples :</p>

<ul>
<li>passer à un hash d&#8217;options dès qu&#8217;on dépasse 3-4 paramètres, ou qu&#8217;on a au moins deux paramètres de même type (donc ambigüs à l&#8217;appel)</li>
<li>fournir des valeurs par défaut clairement regroupées et explicitées pour toutes les options, voire pour certains paramètres.</li>
<li>si on propose plusieurs signatures (de la plus courte pour les cas majoritaires à la plus longue pour un cas sur-mesure), normaliser vers la signature longue avant le reste du code, afin de n&#8217;écrire qu&#8217;une version de l&#8217;implémentation.</li>
</ul>


<p>Prenons pour exemple une fonction <code>callAjax</code> dans l&#8217;esprit de celle de jQuery.  En documentant ses appels avant de l&#8217;implémenter, on isole plusieurs types d&#8217;appel afin d&#8217;être pratique à appeler pour tous :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Makes an Ajax call.  This can be called in a very concise way, with just the endpoint</span>
</span><span class='line'><span class="c1">// URL, if you don&#39;t care about callbacks or behavior changes (the URL will be called through</span>
</span><span class='line'><span class="c1">// HTTP GET).  You can also specify just a success callback, or a success and an error, or</span>
</span><span class='line'><span class="c1">// provide a full-blown options hash to fine-tune the behavior.</span>
</span><span class='line'><span class="c1">//</span>
</span><span class='line'><span class="c1">// Example calls:</span>
</span><span class='line'><span class="c1">//</span>
</span><span class='line'><span class="c1">//   callAjax(&#39;/files&#39;)</span>
</span><span class='line'><span class="c1">//   callAjax(&#39;/files&#39;, function success(res) { … })</span>
</span><span class='line'><span class="c1">//   callAjax(&#39;/files&#39;, successCallback, errorCallback)</span>
</span><span class='line'><span class="c1">//   callAjax(&#39;/files&#39;, {</span>
</span><span class='line'><span class="c1">//     method: &#39;POST&#39;,</span>
</span><span class='line'><span class="c1">//     dataType: &#39;json&#39;,</span>
</span><span class='line'><span class="c1">//     success: function ajaxSuccess() { … },</span>
</span><span class='line'><span class="c1">//     error: function ajaxError() { … }</span>
</span><span class='line'><span class="c1">//   })</span>
</span><span class='line'><span class="kd">function</span> <span class="nx">callAjax</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Pour une signature polymorphe comme ici, on a plusieurs choix quant à la signature formelle (la liste des <em>paramètres</em>) de la fonction :</p>

<ul>
<li>ne rien mettre et tout traiter dynamiquement dans la fonction <em>via</em> <code>arguments</code></li>
<li>ne poser que les paramètres invariables (ici l&#8217;URL) et gérer le reste via <code>arguments</code></li>
<li>faire un mix des deux…</li>
</ul>


<p>Nous allons opter ici pour la deuxième approche.  L&#8217;idée est de normaliser l&#8217;appel vers sa version la plus complexe, donc avec un hash d&#8217;options.  On commencerait donc comme ceci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">callAjax</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">options</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">||</span> <span class="p">{};</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isFunction</span><span class="p">(</span><span class="nx">options</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">success</span><span class="o">:</span> <span class="nx">options</span><span class="p">,</span> <span class="nx">error</span><span class="o">:</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="p">};</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="c1">// …</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>On gère ainsi les cas suivants :</p>

<ul>
<li>pas de deuxième argument (ou deuxième argument <em>falsy</em>, ce qui n&#8217;est pas valide pour notre signature) : <code>options</code> est un objet vide (<code>{}</code>)</li>
<li>le deuxième argument est une fonction : il s&#8217;agit alors du callback de succès, éventuellement suivi de celui d&#8217;erreur : on normalise vers un hash d&#8217;options avec les deux clés appropriées.  Faute de troisième argument, <code>options.error</code> sera présent mais vaudra <code>undefined</code>.</li>
<li>le deuxième argument est un hash d&#8217;options : on n&#8217;y touche pas.</li>
</ul>


<p>Pour gérer les valeurs par défaut, il suffit de définir un conteneur pour toutes celles-ci et de fusionner dans <code>options</code> toutes les clés absentes ou dont la valeur est <code>undefined</code>.  On documente en général les valeurs possibles pour chaque option en écrivant le conteneur.  Un emplacement plutôt valable pour celui-ci est une propriété <code>defaults</code> ou <code>defaultOptions</code> sur la fonction :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">callAjax</span><span class="p">.</span><span class="nx">defaults</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Possible data types are &#39;html&#39;, &#39;json&#39;, &#39;js&#39;, &#39;jsonp&#39; and &#39;xml&#39;</span>
</span><span class='line'>  <span class="nx">dataType</span><span class="o">:</span> <span class="s1">&#39;html&#39;</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// Error callback.  Called with the response text and XHR object.</span>
</span><span class='line'>  <span class="nx">error</span><span class="o">:</span> <span class="nx">$</span><span class="p">.</span><span class="nx">noop</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// HTTP verb.  If not &#39;GET&#39; or &#39;POST&#39;, will emulate using a &#39;POST&#39; and injecting</span>
</span><span class='line'>  <span class="c1">// a `_method` parameter with the passed verb.</span>
</span><span class='line'>  <span class="nx">method</span><span class="o">:</span> <span class="s1">&#39;GET&#39;</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// Success callback.  Called with the response text (or parsed object according to</span>
</span><span class='line'>  <span class="c1">// `dataType`) and XHR object.</span>
</span><span class='line'>  <span class="nx">success</span><span class="o">:</span> <span class="nx">$</span><span class="p">.</span><span class="nx">noop</span>
</span><span class='line'><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure>


<p>Il est ainsi facile pour l&#8217;utilisateur de modifier globalement les valeurs par défaut.  Si on souhaite interdire ça par mesure de sécurité/compatibilité, et qu&#8217;on est sur une <em>runtime</em> ES5, on peut toujours faire suivre la définition d&#8217;un <code>Object.freeze(callAjax.defaults)</code>.  Une autre approche consisterait à enfermer la fonction et ses défauts dans une <em>closure</em> et ne publier que la fonction.</p>

<p>Pour exploiter ces paramètres par défaut, rien de plus simple.  Une fois <code>options</code> normalisé dans la fonction, on procède ainsi :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">opt</span> <span class="k">in</span> <span class="nx">callAjax</span><span class="p">.</span><span class="nx">defaults</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isUndefined</span><span class="p">(</span><span class="nx">options</span><span class="p">[</span><span class="nx">opt</span><span class="p">]))</span>
</span><span class='line'>    <span class="nx">options</span><span class="p">[</span><span class="nx">opt</span><span class="p">]</span> <span class="o">=</span> <span class="nx">callAjax</span><span class="p">.</span><span class="nx">defaults</span><span class="p">[</span><span class="nx">opt</span><span class="p">];</span>
</span><span class='line'><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure>


<p>En fait, ce type de schéma est si fréquent qu&#8217;il porte un nom usuel : <code>extend</code>.  On en trouve des implémentations globalement équivalentes dans la majorité des bibliothèques, de jQuery à Prototype en passant par Underscore.  Du coup, le code plus fréquent pour ce type de besoin est le suivant :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">options</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">extend</span><span class="p">({},</span> <span class="nx">callAjax</span><span class="p">.</span><span class="nx">defaults</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Le reste du code de la fonction n&#8217;a plus qu&#8217;à exploiter les arguments fixes (<code>url</code>) et le contenu d’<code>options</code>.</p>

<h2>8. Ne pas concaténer en masse les chaînes</h2>

<p>En JavaScript il est fréquent de devoir construire petit à petit une chaîne de caractères massive ; il s&#8217;agit le plus souvent de HTML qu&#8217;on compose au fil de l&#8217;eau, à la main faute de mécanisme de <em>templating</em>.  Vous savez, ce genre de code :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// BEUARK</span>
</span><span class='line'><span class="kd">function</span> <span class="nx">buildHTML</span><span class="p">(</span><span class="nx">names</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="s1">&#39;&lt;ul&gt;&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">names</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span>
</span><span class='line'>    <span class="nx">result</span> <span class="o">+=</span> <span class="s1">&#39;&lt;li&gt;&#39;</span> <span class="o">+</span> <span class="nx">_</span><span class="p">.</span><span class="nx">escape</span><span class="p">(</span><span class="nx">names</span><span class="p">[</span><span class="nx">index</span><span class="p">])</span> <span class="o">+</span> <span class="s1">&#39;&lt;/li&gt;&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">result</span> <span class="o">+=</span> <span class="s1">&#39;&lt;/ul&gt;&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ce genre de code est très peu performant.  C&#8217;est comme en Java : une <code>String</code> est non modifiable, et du coup <code>+=</code> entraîne à chaque fois la création d&#8217;une nouvelle chaîne, ce qui implique qu&#8217;il faudra nettoyer la mémoire occupée par la précédente.  Et plus c&#8217;est long, plus c&#8217;est lourd.</p>

<p>Tout comme on recommande en Java de recourir à <code>StringBuffer</code> voire <code>StringBuilder</code>, en JavaScript la meilleure approche consiste à enquiller les fragments dans un tableau, pour au final faire le <code>join</code> qui regroupe tout ça :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">buildHTML</span><span class="p">(</span><span class="nx">names</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;&lt;ul&gt;&#39;</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">names</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span>
</span><span class='line'>    <span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s1">&#39;&lt;li&gt;&#39;</span> <span class="o">+</span> <span class="nx">_</span><span class="p">.</span><span class="nx">escape</span><span class="p">(</span><span class="nx">names</span><span class="p">[</span><span class="nx">index</span><span class="p">])</span> <span class="o">+</span> <span class="s1">&#39;&lt;/li&gt;&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s1">&#39;&lt;/ul&gt;&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nx">result</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span> <span class="c1">// ou join(&#39;\n&#39;)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Les performances n&#8217;ont <a href="http://jsperf.com/string-vs-array-concat">rien à voir</a>, surtout sur de grandes quantités.  Et pour les petites, le code n&#8217;est pas plus compliqué, alors autant normaliser…</p>

<h2>9. Réutiliser ses gros tableaux</h2>

<p>Il arrive de temps en temps qu&#8217;on ait fini de bosser sur un tableau et qu&#8217;on veuille repartir sur un « tableau neuf ».  Parfois, ce sont de <em>très gros</em> tableaux, comme par exemple ceux qu&#8217;on utilise pour calculer un filtre sur les pixels d&#8217;un <code>&lt;canvas&gt;</code>…  On a alors tendance à faire :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// travail sur un tableau &quot;arr&quot; qui devient maousse…</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// « remise à zéro » -- SAYBOF</span>
</span><span class='line'><span class="nx">arr</span> <span class="o">=</span> <span class="p">[];</span>
</span></code></pre></td></tr></table></div></figure>


<p>En fait, cette affectation est sans surprise : elle envoie l&#8217;ancien tableau à la casse (il faudra en récupérer la mémoire) et crée un nouveau tableau, tout petit, qui devra donc lui aussi demander toujours davantage de mémoire au fil de son utilisation.  C&#8217;est un peu dommage d&#8217;avoir basardé toute cette RAM alors qu&#8217;on en aura sans doute besoin juste après.  Et jouer avec <code>new Array(length)</code> ne change rien à l&#8217;affaire : ça ne préalloue pas la mémoire pour autant.</p>

<p>Mais surprise ! La propriété <code>length</code> d&#8217;un tableau est en <em>lecture/écriture</em>.  On peut donc s&#8217;en servir pour <em>réutiliser un tableau existant</em> et sa mémoire allouée, comme ceci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// travail sur un tableau &quot;arr&quot; qui devient maousse…</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// « remise à zéro » -- La classe</span>
</span><span class='line'><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Là aussi, les perfs obtenues sont largement meilleures pour les cas où les tableaux grandissent significativement au fil du temps.</p>

<h2>10. Convertir les nombres correctement</h2>

<p>Figurez-vous que <code>parseInt</code> est un menteur doublé d&#8217;un salaud et que <code>parseFloat</code> est juste la version pourrie de <code>Number(…)</code>.  Après cette phrase un brin raccoleuse (mais parfaitement véridique), je vous invite à consulter tous les détails dans l&#8217;article que je publiais fin décembre : <a href="http://www.js-attitude.fr/2012/12/26/convertir-un-nombre-en-texte-en-javascript/">Convertir un texte en nombre en JavaScript</a></p>

<h2>Envie d&#8217;en savoir plus ?</h2>

<p>Nos ateliers de formation JavaScript couvrent ce genre d&#8217;aspects explicitement ou à travers tous leurs codes, et beaucoup, beaucoup plus encore.  Jetez-y un œil, en plus ils sont bien moins chers que la moyenne du marché !</p>

<ul>
<li><a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> s&#8217;intéresse au langage lui-même, y compris pour des usages très avancés.</li>
<li><a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> explore l&#8217;écosystème front-end en détail et permet la réalisation de bout-en-bout d&#8217;une <em>Single-Page App</em> ultra-moderne mettant en œuvre de façon intégrée tout plein de technos « HTML5 » à l&#8217;aide d&#8217;un outillage développeur de premier plan.</li>
<li><a href="http://www.js-attitude.fr/js-total/">JS Total</a> reprend les deux autres et rajoute les problématiques de tests automatisés, documentation, optimisations tous azimuts et web mobile.</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Dernière chance pour les sessions de janvier !]]></title>
    <link href="http://www.js-attitude.fr/2013/01/14/derniere-minute-sessions-janvier/"/>
    <updated>2013-01-14T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2013/01/14/derniere-minute-sessions-janvier</id>
    <content type="html"><![CDATA[<p>Le mois de janvier est manifestement « un peu trop tôt » pour planifier des formations…  La majorité des dates prévues ce mois-ci manque cruellement d&#8217;inscriptions.</p>

<p>La session <strong><a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> des 22 et 23 janvier</strong> (oui, c&#8217;est la semaine prochaine) se dirige droit vers une annulation, faute d’avoir suffisamment d’inscrits.  C&#8217;est particulièrement dommage, car avec la <a href="http://www.js-attitude.fr/js-total/">JS Total</a> de février déjà complète, elle constitue une bonne alternative (surtout en duo avec la <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> de février) pour bénéficier des contenus les plus « sexy » de JS Total.</p>

<p>Nos conditions d&#8217;annulation étant ce qu&#8217;elles sont, nous devrons statuer sur cette session au plus tard demain après-midi.</p>

<p>Nous avons donc décidé de tenter une petite opération de réduction visant à ramener assez de places pour la maintenir.  Pour ces dates uniquement, <strong>nous baissons donc tous les tarifs de 100€ HT</strong>, ce qui donne, <em>par personne</em> :</p>

<ul>
<li>799€ HT seulement (jusqu&#8217;à 2 personnes)</li>
<li>699€ HT seulement (de 3 à 5 personnes)</li>
<li>599€ HT seulement (à partir de 6 personnes)</li>
<li>664€ HT seulement (tarif fidélité : votre société nous a réglé au moins 1000€ HT sur les 12 mois écoulés)</li>
</ul>


<p>Notez que vous pouvez constituer un groupe multi-sociétés : si vous nous adressez une <a href="http://www.js-attitude.fr/demander-une-convention/">demande de convention</a> précisant l&#8217;ensemble des noms et infos de société, nous pourrons appliquer le tarif de groupe approprié à l&#8217;ensemble des participants concernés.</p>

<p>Comme <a href="http://www.js-attitude.fr/js-guru/#programme">le programme</a> devrait vous en convaincre, c&#8217;est une formation très alléchante.  À un tarif pareil, il n&#8217;y a pas à hésiter !</p>

<p><em>(et dans la même série, on a deux sessions Git à la fin du mois qui ont encore plein de places et sont super intéressantes : <a href="http://www.git-attitude.fr/git-au-quotidien/">Git au Quotidien</a> le 29 et <a href="http://www.git-attitude.fr/git-avance/">Git Avancé</a> le 30)</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Début 2013 chez JS Attitude]]></title>
    <link href="http://www.js-attitude.fr/2013/01/02/debut-2013-chez-js-attitude/"/>
    <updated>2013-01-02T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2013/01/02/debut-2013-chez-js-attitude</id>
    <content type="html"><![CDATA[<p>Et voilà, on est en 2013…</p>

<p>Delicious Insights et son cycle de formations JS Attitude vous souhaitent une excellente nouvelle année, avec plein de bonnes choses dedans, et notamment davantage de plaisir au travail.  C&#8217;est le moment de planifier vos formations pour ce début d&#8217;année !  Et JS Attitude vous propose bon nombre de sessions pour le premier trimestre :</p>

<ul>
<li>22–23/01 : <a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> en <strong>format 2 jours</strong> (dépêchez-vous !).  Outre son intérêt propre, cette session fournit une alternative intéressante pour tous ceux qui ne pourront pas assister à JS Total en février, faute de places…</li>
<li>05–08/02 : <a href="http://www.js-attitude.fr/js-total/">JS Total</a> ; notre blockbuster a toutefois, comme d&#8217;habitude, affiché complet 6 semaines avant la date…  Une <strong>excellente alternative</strong>, qui est aussi légèrement meilleur marché, consiste à s&#8217;inscrire au JS Guru 2 jours des 22–23/01 et au JS Puissant du 19/02, ce qui vous fournit à peu près 80% des savoirs dispensés par JS Total.  Il reste pas mal de places sur ces 2 sessions.  La prochaine JS Total n&#8217;aura lieu qu&#8217;en avril (dates à venir).</li>
<li>19/02 : <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a>, une formation qui à mon sens constitue un incontournable pour tout développeur JS sérieux.</li>
<li>26/02 : <a href="http://www.js-attitude.fr/coffee-script">CoffeeScript</a>.  La voie royale vers (beaucoup) plus de bonheur dans votre JavaScript quotidien.  Contrairement à fin 2012, les places pour cette session partent assez vite, alors dépêchez-vous !</li>
<li>18–19/03 : <a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> en <strong>format 2 jours</strong></li>
</ul>


<p>Dépêchez-vous de <a href="http://www.js-attitude.fr/demander-une-convention/">demander une convention de formation</a>.  Et souvenez-vous : Delicious Insights est un organisme de formation agréé, éligible aux prises en charge par OPCA (dont les DIF), nous sommes presque moitié moins chers que le marché en dépit de prestations haut de gamme et en avance sur ce dernier, et <em>nous ne demandons pas de versement d&#8217;acompte</em> : vous réglez jusqu&#8217;à 30 jours après la session !  Alors n&#8217;hésitez plus !</p>

<p>Sachez par ailleurs qu&#8217;il nous reste comme disponibilités pour de l&#8217;<em>intra-entreprises</em> :</p>

<ul>
<li>1 jour en janvier (24, 25 ou 31)</li>
<li>2 jours en février (20, 21, 22, 27 ou 28)</li>
<li>plus rien en mars (!)</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Convertir un texte en nombre en JavaScript]]></title>
    <link href="http://www.js-attitude.fr/2012/12/26/convertir-un-nombre-en-texte-en-javascript/"/>
    <updated>2012-12-26T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2012/12/26/convertir-un-nombre-en-texte-en-javascript</id>
    <content type="html"><![CDATA[<p>Quoi de plus simple, a priori, que de convertir un texte en nombre en JavaScript ?  Souvent, on n&#8217;a même pas l&#8217;impression d&#8217;en avoir besoin.  Et sinon, on recourt à <code>parseInt</code> ou <code>parseFloat</code>, vite fait…</p>

<p>Et pourtant…  Que de pièges, que de subtilités de fonctionnement nous attendent sur un sujet au premier abord aussi basique.  Explorons tout ça ensemble.</p>

<!-- more -->




<div class="update">
  <p><strong>Mise à jour du 29/12 13:46</strong> : suite à des échanges avec le commentateur identifié comme « check_ca », j&#8217;ai décidé de compléter l&#8217;article pour parler de <code>Number</code> en tant que fonction, du cas des infinis, et proposer une version certes minusculement moins performante de <code>cleanInt</code> mais plus lisible et universelle.</p>
</div>


<h2>A-t-on besoin de convertir ?</h2>

<p>Comme bien souvent, la vraie réponse est : ça dépend.</p>

<p>Dans la mesure où je vous recommande par ailleurs de toujours comparer avec <code>===</code> sauf cas spécifique bien identifié, vous aurez en effet besoin, si vous appliquez cette consigne, de convertir explicitement vos nombres « textuels » en nombres effectifs (type <code>Number</code>) pour obtenir une comparaison valide.</p>

<p>Toutefois, certains opérateurs qui n&#8217;ont de sens que sur les nombres (ou principalement sur les nombres) entraîneront automatiquement une conversion numérique de leurs arguments.  On parle alors de <em>protocole de conversion implicite</em>.  C&#8217;est notamment le cas des opérateurs arithmétiques, à l&#8217;exception du cas « <code>String</code> plus quelque chose ».  Toutefois, l&#8217;enchaînement de protocoles de conversion, chaque opérande étant traité indépendamment et à tour de rôle, peut donner à terme des <code>String</code> là où on aurait cru des <code>Number</code>, ce qui n&#8217;est pas sans surprise…</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="mi">5</span> <span class="o">+</span> <span class="mi">2</span>           <span class="c1">// =&gt; 7</span>
</span><span class='line'><span class="s1">&#39;5&#39;</span> <span class="o">+</span> <span class="mi">2</span>         <span class="c1">// =&gt; &#39;52&#39;</span>
</span><span class='line'><span class="mi">5</span> <span class="o">+</span> <span class="s1">&#39;2&#39;</span>         <span class="c1">// =&gt; &#39;52&#39;</span>
</span><span class='line'><span class="s1">&#39;5&#39;</span> <span class="o">+</span> <span class="s1">&#39;2&#39;</span>       <span class="c1">// =&gt; &#39;52&#39;</span>
</span><span class='line'><span class="p">[]</span> <span class="o">+</span> <span class="mi">3</span>          <span class="c1">// =&gt; &#39;3&#39;</span>
</span><span class='line'><span class="mi">3</span> <span class="o">+</span> <span class="p">[]</span>          <span class="c1">// =&gt; &#39;3&#39;</span>
</span><span class='line'><span class="p">{}</span> <span class="o">+</span> <span class="mi">3</span>          <span class="c1">// =&gt; 3 ou &#39;[object Object]3&#39;, selon version de JS</span>
</span><span class='line'><span class="mi">3</span> <span class="o">+</span> <span class="p">{}</span>          <span class="c1">// =&gt; &#39;3[object Object]&#39;</span>
</span><span class='line'><span class="kc">false</span> <span class="o">+</span> <span class="mi">3</span>       <span class="c1">// =&gt; 3</span>
</span><span class='line'><span class="mi">3</span> <span class="o">+</span> <span class="kc">true</span>        <span class="c1">// =&gt; 4</span>
</span><span class='line'><span class="mi">3</span> <span class="o">+</span> <span class="kc">null</span>        <span class="c1">// =&gt; 3</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">x</span><span class="p">;</span> <span class="nx">x</span> <span class="o">+</span> <span class="mi">3</span>    <span class="c1">// =&gt; NaN</span>
</span></code></pre></td></tr></table></div></figure>


<p>Dans les exemples ci-dessus, on voit que l&#8217;opérateur <code>+</code> entraîne souvent des conversions amenant à <code>String</code>, mais propose aussi pas mal de cas où le résultat est, de façon inattendue parfois, un <code>Number</code>.  Les opérateurs moins ambigüs, tels que <code>-</code> ou <code>*</code>, fonctionnent presque toujours en <code>Number</code> (par exemple, <code>3 - []</code> est toujours 3), quitte à renvoyer <code>NaN</code> (qui comme son nom ne l&#8217;indique pas est bien de type <code>Number</code>…).</p>

<p>Le problème, évidemment, c&#8217;est qu&#8217;on ne va pas commencer à se souvenir de tous les cas de figure, opérateur par opérateur, et types d&#8217;opérande par types d&#8217;opérande.  D&#8217;où la nécessité de clarifier parfois les choses en forçant explicitement le type de nos opérandes à <code>Number</code>, de façon contrôlée.</p>

<p>Pour ce faire, la majorité des auteurs de code JavaScript ont recours, suivant le besoin (entier ou flottant), à <code>parseInt</code> et <code>parseFloat</code>.  À mon sens, c&#8217;est plus problématique qu&#8217;autre chose.</p>

<h2>Méfie-toi de <code>parseInt</code> et <code>parseFloat</code></h2>

<p>Les deux ne se comportent pas exactement pareil.  Comme leurs noms l&#8217;indiquent, le premier renvoie un entier (un <code>Number</code> tronqué sur sa partie entière) et l&#8217;autre un flottant (toujours un <code>Number</code>, mais non tronqué).  Mais ce n&#8217;est pas tout.  Par exemple, avant ES5 (testez sur une console JS qui ne force pas ES5, ou dans une REPL node par exemple), on obtenait ceci :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Pre-ES5 -- consoles Firefox, Safari, node, etc.  Mais pas Chrome !</span>
</span><span class='line'><span class="nb">parseFloat</span><span class="p">(</span><span class="s1">&#39;08&#39;</span><span class="p">)</span> <span class="c1">// =&gt; 8</span>
</span><span class='line'><span class="nb">parseInt</span><span class="p">(</span><span class="s1">&#39;08&#39;</span><span class="p">)</span>   <span class="c1">// =&gt; 0 -- OMGWTFBBQ?!</span>
</span></code></pre></td></tr></table></div></figure>


<p>C&#8217;est un problème bien connu : <code>parseInt</code> accepte en fait <em>deux</em> arguments : le texte <em>et une base optionnelle</em> (de 2 à 36) dans lequel ce texte encode le nombre.  Mais avant EcmaScript 5, au lieu de supposer une base 10 (ce qui, de l&#8217;avis général, serait nettement plus utile), il <em>devine</em>.  Aïe.  En l&#8217;occurrence, il se base sur les syntaxes C/Java/JS/etc. de litéraux entiers, donc démarrer par <code>0x</code> ou <code>0X</code> indique un hexadécimal, sinon démarrer par <code>0</code> indique un octal ; les chiffres octaux valides allant de 0 à 7, le 8 est invalide.</p>

<p>Incidemment, JSLint (comme JSHint, je crois) vous couineront à l&#8217;oreille s&#8217;ils vous voient faire un <code>parseInt</code> qui ne précise pas la base.  Et ils auront raison.</p>

<p>Vous me direz : <em>« mais alors, <code>parseInt('08')</code> devrait plutôt renvoyer <code>NaN</code>, non ?! »</em>.  Et je serais bien d&#8217;accord avec vous.  Seulement voilà : <strong><code>parseInt</code> et <code>parseFloat</code> se contentent d&#8217;ignorer la suite du texte dès qu&#8217;ils rencontrent un caractère invalide</strong>.  Ce qui est un comportement <em>pourri</em>, mais toujours d&#8217;actualité.</p>

<p>Je ne sais pas vous, mais moi, si je demande à l&#8217;internaute de saisir un nombre et qu&#8217;il me pond <code>42foobar</code>, je ne veux pas « voir » 42, je veux me prendre un <code>NaN</code>.  Pas de chance :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nb">parseInt</span><span class="p">(</span><span class="s1">&#39;42foobar&#39;</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="nb">parseFloat</span><span class="p">(</span><span class="s1">&#39;42foobar&#39;</span><span class="p">)</span>   <span class="c1">// =&gt; 42</span>
</span></code></pre></td></tr></table></div></figure>


<p>Alors que faire ?</p>

<h2>Le protocole de conversion numérique de JavaScript</h2>

<p>Il se trouve que JavaScript est depuis toujours équipé d&#8217;un mécanisme qui convertit une entité quelconque en <code>Number</code> : c&#8217;est son protocole de conversion numérique, que la spec appelle affectueusement « <code>ToNumber</code> ».  Il est déclenché implicitement lors d&#8217;expressions nécessitant un traitement numérique d&#8217;un opérande.</p>

<p>La manière la plus simple de transformer une valeur (ou <code>undefined</code>) en <code>Number</code> consiste probablement à la passer à l&#8217;opérateur <code>+</code> unaire (c&#8217;est-à-dire ne prenant qu&#8217;un opérande) : <code>+truc</code>.  Bon point pour lui : il refusera tout caractère invalide.  Voyez plutôt :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="o">+</span><span class="mi">42</span>          <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="o">+</span><span class="s1">&#39;42&#39;</span>        <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="o">+</span><span class="s1">&#39;08&#39;</span>        <span class="c1">// =&gt; 8</span>
</span><span class='line'><span class="o">+</span><span class="s1">&#39;0x10&#39;</span>      <span class="c1">// =&gt; 16</span>
</span><span class='line'><span class="o">+</span><span class="s1">&#39;42.17&#39;</span>     <span class="c1">// =&gt; 42.17</span>
</span><span class='line'><span class="o">+</span><span class="s1">&#39;42foobar&#39;</span>  <span class="c1">// =&gt; NaN -- aaaaah !</span>
</span><span class='line'><span class="o">+</span><span class="s1">&#39;   42   &#39;</span>  <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="o">+</span><span class="p">{}</span>          <span class="c1">// =&gt; NaN -- pas de conversion générique Object -&gt; Number</span>
</span><span class='line'><span class="o">+</span><span class="p">[]</span>          <span class="c1">// =&gt; 0 -- &lt;=&gt; +([].toString()) &lt;=&gt; +&#39;&#39;</span>
</span><span class='line'><span class="o">+</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>         <span class="c1">// =&gt; 3 -- &lt;=&gt; +&#39;3&#39;</span>
</span><span class='line'><span class="o">+</span><span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>      <span class="c1">// =&gt; NaN  &lt;=&gt; +&#39;3,4&#39;</span>
</span><span class='line'><span class="o">+</span><span class="kc">false</span>       <span class="c1">// =&gt; 0</span>
</span><span class='line'><span class="o">+</span><span class="kc">true</span>        <span class="c1">// =&gt; 1</span>
</span><span class='line'><span class="o">+</span><span class="kc">null</span>        <span class="c1">// =&gt; 0</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">x</span><span class="p">;</span> <span class="o">+</span><span class="nx">x</span>    <span class="c1">// =&gt; NaN</span>
</span></code></pre></td></tr></table></div></figure>


<p>Comme vous pouvez le voir, le <code>+</code> unaire est un moyen rapide, concis et efficace de convertir ce qu&#8217;on veut en <code>Number</code>.  Il ne change pas le signe éventuel et réagit à tout caractère invalide en retournant <code>NaN</code>.  Il est donc en tous points supérieur à <code>parseFloat</code>.</p>

<p>Il faut souligner qu&#8217;il existe une manière plus explicite de déclencher la conversion : il suffit d&#8217;employer <code>Number</code> comme fonction, conformément à la section 15.7.1.1 de la spec (ES3) :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nb">Number</span><span class="p">(</span><span class="s1">&#39;0x10&#39;</span><span class="p">)</span>      <span class="c1">// =&gt; 16</span>
</span><span class='line'><span class="nb">Number</span><span class="p">(</span><span class="s1">&#39;42.17&#39;</span><span class="p">)</span>     <span class="c1">// =&gt; 42.17</span>
</span><span class='line'><span class="nb">Number</span><span class="p">(</span><span class="s1">&#39;42foobar&#39;</span><span class="p">)</span>  <span class="c1">// =&gt; NaN</span>
</span><span class='line'><span class="nb">Number</span><span class="p">(</span><span class="kc">false</span><span class="p">)</span>       <span class="c1">// =&gt; 0</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">x</span><span class="p">;</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>    <span class="c1">// =&gt; NaN</span>
</span></code></pre></td></tr></table></div></figure>


<p>C&#8217;est certes un peu plus verbeux que le <code>+</code> unaire, mais nettement plus lisible pour les débutants…</p>

<p>Le seul souci potentiel, c&#8217;est que ce protocole de conversion ne fournit pas d&#8217;équivalent à <code>parseInt</code>, au sens où il ne tronque jamais sur la partie entière.  Comment obtenir ce comportement ?  Selon que vous voulez préserver un résultat <code>NaN</code> sur les textes pourris ou non, la solution varie.</p>

<h2>Et pour garantir des entiers ?</h2>

<p>On a deux manières de procéder :</p>

<ul>
<li>une qui est aussi performante que possible mais ignore les infinis et les NaN</li>
<li>une qui est plutôt lisible et préserve les infinis (sait-on jamais…), au prix d&#8217;une performance très légèrement inférieure (ce qui n&#8217;est généralement pas un souci).</li>
</ul>


<p>Voyons-les tour à tour.</p>

<h3>La méthode « hack », ultra-performante mais peu lisible et non sans limites</h3>

<p>À condition que ça ne vous dérange pas d&#8217;être à zéro par défaut (textes moisis compris), vous pouvez tirer parti de la sémantique de l&#8217;opérateur <em>ou bit-à-bit</em>, à savoir le <em>pipe</em> simple (<code>|</code>) :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="mf">42.17</span> <span class="o">|</span><span class="err"> </span><span class="mi">0</span>       <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="o">-</span><span class="mf">42.3</span> <span class="o">|</span> <span class="mi">0</span>       <span class="c1">// =&gt; -42</span>
</span><span class='line'><span class="s1">&#39;42&#39;</span>  <span class="o">|</span> <span class="mi">0</span>       <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="s1">&#39;42.13&#39;</span> <span class="o">|</span> <span class="mi">0</span>     <span class="c1">// =&gt; 42</span>
</span><span class='line'><span class="s1">&#39;-17.7&#39;</span> <span class="o">|</span> <span class="mi">0</span>     <span class="c1">// =&gt; -17</span>
</span><span class='line'><span class="s1">&#39;0x10&#39;</span> <span class="o">|</span> <span class="mi">0</span>      <span class="c1">// =&gt; 16</span>
</span><span class='line'><span class="s1">&#39;42foobar&#39;</span> <span class="o">|</span> <span class="mi">0</span>  <span class="c1">// =&gt; 0 -- pas NaN</span>
</span><span class='line'><span class="s1">&#39;xyz&#39;</span> <span class="o">|</span> <span class="mi">0</span>       <span class="c1">// =&gt; 0 -- pas NaN</span>
</span></code></pre></td></tr></table></div></figure>


<p>À ce stade, vous avez probablement trois questions :</p>

<ul>
<li><strong>Pourquoi est-ce que ça force les entiers ?</strong> C&#8217;est parce que selon la section 11.10 de la spec (pour ES3 en tout cas, mais la sémantique persiste en ES5), les opérandes sont passés par une conversion interne <code>ToInt32</code>, pour en faire des entiers signés 32-bit (oui, attention, pas 64-bit !).</li>
<li><strong>Pourquoi est-ce que ça ne fait pas de NaN ?</strong> Parce que la spec de <code>ToInt32</code> revient à passer par <code>ToNumber</code> puis, pour tous les cas « foireux » (NaN, zéros signés et infinis), à remplacer par <code>0</code> (section 9.5 de la spec ES3).</li>
<li><strong>Pourquoi le OU et pas une autre opération bit-à-bit ?</strong>  Il nous faut une opération neutre sur l&#8217;entier d&#8217;origine (le résultat du <code>ToInt32</code> sur votre texte).  Passer par un ET (<code>&amp;</code>) serait donc assez pénible car il nous faudrait un masque intégral, alors que le OU (<code>|</code>) et le OU exclusif (XOR, <code>^</code>) sont neutres à zéro.  J&#8217;imagine que le <em>pipe</em> a gagné de peu sur le <em>caret</em>  parce qu&#8217;il est plus souvent tapé…</li>
</ul>


<p>Petit conseil d&#8217;ami : si vous employez une telle syntaxe, ajoutez un commentaire sur la ligne précédente indiquant que vous faites une conversion entière à zéro par défaut : ce n&#8217;est vraiment pas lisible tel quel…</p>

<h4>OK, mais si je veux du <code>NaN</code> pour les textes moisis ?</h4>

<p>C&#8217;est en effet un cas de figure probable.  Pour le gérer correctement, vous devrez probablement combiner la conversion <code>ToNumber</code> classique et le déclenchement implicite de <code>ToInt32</code> au moyen d&#8217;un ou bit-à-bit :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">cleanInt</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">x</span> <span class="o">=</span> <span class="o">+</span><span class="nx">x</span><span class="p">;</span> <span class="c1">// x = Number(x);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nb">isNaN</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="o">?</span> <span class="nx">x</span> <span class="o">:</span> <span class="p">(</span><span class="nx">x</span> <span class="o">|</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;-42.17&#39;</span><span class="p">)</span>   <span class="c1">// =&gt; -42</span>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;42foobar&#39;</span><span class="p">)</span> <span class="c1">// =&gt; NaN</span>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;Infinity&#39;</span><span class="p">)</span> <span class="c1">// =&gt; 0 -- hmmm…</span>
</span></code></pre></td></tr></table></div></figure>


<h3>La méthode un poil moins performante, mais lisible et universelle</h3>

<p>Quitte à faire une fonction dédiée, autant préserver les infinis aussi.  Pour cela, plutôt que de passer par l&#8217;absconse syntaxe <code>| 0</code>, utilisons les fonctions d&#8217;arrondi de JavaScript.  C&#8217;est certes un micro-poil moins rapide, mais ça ne devrait généralement pas nous poser de souci concret.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">cleanInt</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">x</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="o">:</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">ceil</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;-42.17&#39;</span><span class="p">)</span>    <span class="c1">// =&gt; -42</span>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;42foobar&#39;</span><span class="p">)</span>  <span class="c1">// =&gt; NaN</span>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;Infinity&#39;</span><span class="p">)</span>  <span class="c1">// =&gt; Infinity</span>
</span><span class='line'><span class="nx">cleanInt</span><span class="p">(</span><span class="s1">&#39;-Infinity&#39;</span><span class="p">)</span> <span class="c1">// =&gt; -Infinity</span>
</span></code></pre></td></tr></table></div></figure>


<p>Examinons les cas possibles :</p>

<ul>
<li><strong><code>x</code> est un texte moisi ou <code>x</code> est <code>NaN</code></strong> : il sera <code>NaN</code> au final, la condition sera fausse (toute comparaison de <code>NaN</code> renvoie <code>false</code>) et <code>Math.ceil</code> préservera <code>NaN</code>.</li>
<li><strong><code>x</code> décrit un nombre valide positif ou nul</strong> : on utilisera l&#8217;arrondi à l&#8217;entier immédiatement inférieur, <code>Math.floor</code>.</li>
<li><strong><code>x</code> décrit un nombre valide négatif</strong> : on utilisera l&#8217;arrondi à l&#8217;entier immédiatement supérieur, <code>Math.ceil</code>.</li>
<li><strong><code>x</code> décrit un infini positif ou négatif</strong> : <code>Math.floor</code> comme <code>Math.ceil</code> préserveront l&#8217;infini concerné.</li>
</ul>


<p>En fait, le ternaire (l&#8217;opérateur <code>… ? … : …</code>) ci-dessus se prête particulièrement bien à une petite optimisation syntaxique, sans nuire pour autant—à mon sens—à la lisibilité, au moyen de l&#8217;opérateur <code>[]</code> qui permet de sélectionner dynamiquement une propriété (donc une méthode) au sein d&#8217;un objet :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">cleanInt</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">x</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nb">Math</span><span class="p">[</span><span class="nx">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="s1">&#39;floor&#39;</span> <span class="o">:</span> <span class="s1">&#39;ceil&#39;</span><span class="p">](</span><span class="nx">x</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>En résumé…</h2>

<ul>
<li><code>parseInt</code> et <code>parseFloat</code> sont juste bons à sucer des cailloux</li>
<li>Le <code>+</code> unaire, ou sa version explicite <code>Number(…)</code>, sont souvent supérieurs à <code>parseFloat</code> car ils renvoient <code>NaN</code> pour les textes moisis</li>
<li>Le <code>… | 0</code> tronque bien sur la partie entière, mais renvoie <code>0</code> pour les textes moisis</li>
<li>On peut facilement combiner les deux pour obtenir une version plus clean de <code>parseInt(…, 10)</code></li>
<li>On peut aussi choisir de sacrifier quelques microsecondes (ahem…) pour gagner en lisibilité en préservant au passage les infinis.</li>
</ul>


<div data-upcoming-sessions="js-puissant" xstyle="display: none;">
  <h2>Envie d’en apprendre davantage&nbsp;?</h2>
  
  <p>Notre atelier <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> explore en profondeur tous les aspects techniques avancés du langage JavaScript lui-même.  Des protocoles de conversion à la programmation fonctionnelle en passant par les méthodes méconnues des types natifs et le fonctionnement des prototypes, cette formation JavaScript vous donne un gros coup de boost dans le développement de vos codes JS quels qu’ils soient.</p>

  <p>Prochaines sessions&nbsp;:</p>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Pourquoi tu ne devrais jamais utiliser new sur les types JavaScript natifs]]></title>
    <link href="http://www.js-attitude.fr/2012/11/22/pourquoi-jamais-new-sur-natifs-en-js/"/>
    <updated>2012-11-22T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2012/11/22/pourquoi-jamais-new-sur-natifs-en-js</id>
    <content type="html"><![CDATA[<p>Qu’est-ce qu’on a comme types natifs en JavaScript ?  Facile : <code>Object</code>, <code>Number</code>, <code>String</code>, <code>Boolean</code>, <code>Array</code>, <code>Date</code>, <code>RegExp</code> et <code>Function</code>.</p>

<p>Et lorsqu’on instancie un objet en JavaScript, on fait généralement <code>new LeType(…)</code>.  Mais dans cet article, je vais vous expliquer pourquoi, à quelques petites exceptions près, pour les types natifs c&#8217;est soit inutilement lourd, soit carrément contre-productif.</p>

<!-- more -->


<p>Allez, on se démonte les types un par un, d&#8217;accord ?</p>

<h2>Object</h2>

<p>De deux choses l’une :</p>

<ul>
<li>soit tu veux instancier un type à toi, et tu vas faire <code>new TonType</code>, pas <code>new Object</code> ;</li>
<li>soit tu veux bien un objet basique tout nu, et alors tu auras largement plus vite fait d&#8217;utiliser <code>{}</code> (ex. <code>var obj = {};</code>).  La version <code>new</code> est inutilement verbeuse, car on a une syntaxe litérale disponible.  Ce sera aussi le cas de plusieurs autres types natifs.</li>
</ul>


<h2>Number</h2>

<p>OK, donc tu veux créer un nouveau nombre.  Explique-moi pourquoi tu irais faire <code>new Number(42)</code> au lieu de juste <code>42</code> ?!?  Tu es payé(e) au caractère ?  Évidemment pas.</p>

<p>En plus, les deux ne se comportent pas de la même façon dans certains cas.  Par exemple, le protocole de conversion booléenne n&#8217;est pas le même : <code>if (new Number(0))</code> passera alors que <code>if (0)</code> non.</p>

<h2>String</h2>

<p>Là aussi, on a une syntaxe litérale : les apostrophes ou guillemets (aucune différence dans le comportement).  Aucune raison de t&#8217;embarasser d&#8217;un <code>new String('foobar')</code> lorsque l&#8217;argument, <code>'foobar'</code>, suffit.</p>

<p>Qui plus est, JavaScript va traiter différemment les objets <code>String</code> (issus d&#8217;un <code>new String(…)</code>) et les chaînes primitives (produites par un litéral).  Ainsi, <code>typeof new String('foo')</code> produit <code>'object'</code> et non <code>'string'</code>. Et <code>eval</code> ne considèrera comme code source qu&#8217;une chaîne primitive, alors qu&#8217;un objet <code>String</code> sera juste renvoyé tel quel.  Autant de raisons de ne jamais recourir à <code>new String</code>…</p>

<h2>Boolean</h2>

<p>On est dans une situation similaire à <code>Number</code> : non seulement les deux litéraux réservés <code>true</code> et <code>false</code> sont suffisants, mais en plus le protocole de conversion booléenne va nous foutre dedans : <code>if (new Boolean(false))</code> passera !  Une bonne raison de ne jamais recourir à <code>new</code> sur ce coup…</p>

<h2>Array</h2>

<p>Dans la mesure où on a une syntaxe litérale (crochets et virgules, ex. <code>[1, 2, 3]</code>), il n&#8217;y a <em>a priori</em> jamais à utiliser <code>new Array(1, 2, 3)</code>…</p>

<p>Il existe juste un cas, finalement assez rare, où le <code>new</code> est toutefois justifié : pour préallouer un tableau à une certaine taille, ce qui se produit si on utilise un unique argument numérique.  Par exemple, <code>new Array(1000000)</code> va créer un tableau d&#8217;un million de cases, toutes pour le moment <code>undefined</code>.  Encore une fois, c&#8217;est un cas de figure assez rare.</p>

<h2>Date</h2>

<p>Pour le coup, <code>new Date</code> est parfaitement justifié, puisqu’on initialise très souvent un objet <code>Date</code> sur la base d&#8217;une valeur précise, que celle-ci soit un numérique (nombre de millisecondes depuis l&#8217;<em>epoch</em>, le 1er janvier 1970 à 0h GMT), une chaîne de caractère compatible ou une série de composantes année, mois, jour, etc.  Il n&#8217;y a tout simplement pas de syntaxe litérale pour les dates, on doit donc recourir à <code>new Date</code>.</p>

<p>Il existe toutefois un cas où je déconseille <code>new Date</code> : lorsqu&#8217;on veut juste récupérer la version numérique du moment présent.  Plutôt que de faire <code>new Date().getTime()</code>, préférez <code>Date.now()</code> : non seulement c&#8217;est nettement plus compact et explicite, mais en plus ça évite de créer inutilement un objet <code>Date</code> à <em>garbage-collecter</em> ensuite…</p>

<h2>RegExp</h2>

<p>On a ici deux cas de figure :</p>

<ul>
<li><strong>La regex est fixe, connue à l&#8217;avance</strong>.  Il est alors inutile de passer par <code>new RegExp</code>, puisqu&#8217;on dispose d&#8217;une syntaxe litérale.  <code>/foo(?:bar)?/ig</code> sera toujours plus court que <code>new RegExp('foo(?:bar)?', 'ig')</code>…  Cependant, si la regex est bourré de slashes (<code>/</code>), je peux comprendre qu&#8217;au bout d&#8217;un moment on préfère éviter de tous les échapper : <code>new RegExp('^https?://foo/bar/baz')</code> peut sembler préférable à <code>/^https?:\/\/foo\/bar\/baz/</code>…</li>
<li><strong>La regex n&#8217;est pas connue à l&#8217;avance</strong>.  Par exemple, elle est calculée sur la base d&#8217;une saisie utilisateur, d&#8217;une réponse Ajax, etc.  Auquel cas on n&#8217;a pas d&#8217;autre choix que de passer par <code>new RegExp</code>.  Imaginons qu&#8217;on développe un <em>fuzzy matcher</em> qui cherche toutes les chaînes de caractères contenant ceux qu&#8217;on saisit, dans le bon ordre mais quelles que soient leurs positions, comme dans les éditeurs TextMate et SublimeText :</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">words</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;déjà&#39;</span><span class="p">,</span> <span class="s1">&#39;demain&#39;</span><span class="p">,</span> <span class="s1">&#39;délicat&#39;</span><span class="p">,</span> <span class="s1">&#39;dommage&#39;</span><span class="p">,</span> <span class="s1">&#39;foobar&#39;</span><span class="p">];</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">input</span> <span class="o">=</span> <span class="s1">&#39;da&#39;</span><span class="p">;</span> <span class="c1">// On l&#39;aurait par exemple prix de $(&#39;#search&#39;).val()…</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">regex</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;.*&#39;</span><span class="p">),</span> <span class="s1">&#39;i&#39;</span><span class="p">);</span> <span class="c1">// =&gt; /d.*a/i</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">[],</span> <span class="nx">word</span><span class="p">;</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">words</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">word</span> <span class="o">=</span> <span class="nx">words</span><span class="p">[</span><span class="nx">index</span><span class="p">];</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">regex</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">word</span><span class="p">))</span>
</span><span class='line'>    <span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">word</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Ou avec Prototype : var result = words.grep(regex);</span>
</span><span class='line'>
</span><span class='line'><span class="nx">result</span> <span class="c1">// =&gt; [&#39;demain&#39;, &#39;délicat&#39;, &#39;dommage&#39;]</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Function</h2>

<p>Il existe trois manières de créer des fonctions en JavaScript :</p>

<ul>
<li>Avec une <em>déclaration</em> : c&#8217;est ce qui se passe quand le mot-clé <code>function</code> est rencontré à un endroit où on attend une <em>instruction</em>.  Il doit alors obligatoirement être suivi d&#8217;un identifiant qui nomme la fonction.  Les déclarations de fonction sont <em>hoisted</em>, c&#8217;est-à-dire qu&#8217;elles sont interprétées comme si elles étaient placées en tout début de portée (donc de l&#8217;éventuelle fonction conteneur).</li>
<li>Avec une <em>expression</em> : c&#8217;est le cas quand le mot-clé <code>function</code> est rencontrée alors qu&#8217;on attend une expression (par exemple, à droite d&#8217;un opérateur <code>=</code>, d&#8217;une parenthèse ouvrante, ou comme argument à une autre fonction).  La fonction n&#8217;est pas obligatoirement nommée (et si elle l&#8217;est, ce nom n&#8217;est valable qu&#8217;à l&#8217;intérieur de la fonction elle-même), et n&#8217;est pas non plus <em>hoisted</em>.</li>
<li>Avec <code>new Function</code>.  Cela permet de créer une fonction dont le code a été déterminé dynamiquement à l&#8217;exécution, mais attention, il existe une différence majeure : là où les déclarations et expressions de fonction entraînent une <em>closure</em> (une fermeture lexicale, qui leur permet d&#8217;accéder à l&#8217;ensemble de la portée), les fonctions obtenues par <code>new Function</code> s&#8217;exécutent dans le contexte global (dans un navigateur, l&#8217;objet <code>window</code>), voire, si on est en EcmaScript 5 et en mode strict (le texte de la fonction démarre par <code>'use strict';</code>), avec un contexte <code>undefined</code>.</li>
</ul>


<p>L&#8217;immense majorité du temps, votre fonction a besoin de sa <em>closure</em> : vous aurez donc recours à une expression de fonction ou à une déclaration.</p>

<p>Dans certains cas très rares toutefois, tels qu&#8217;une évaluation de code arbitraire que vous souhaiteriez « protéger » en lui interdisant tout accès à la <em>closure</em> en vigueur, recourir à <code>new Function</code>, surtout en mode strict si ça vous est possible, est une alternative viable, et souvent préférable, à un bête <code>eval</code>.</p>

<h2>Conclusion</h2>

<p>Comme vous pouvez le voir, au quotidien, il est généralement inutile de recourir à <code>new</code> pour les types natifs, à l&#8217;exception notable de <code>new Date</code> et, de temps en temps, de <code>new RegExp</code>.  Les cas valables de <code>new Array</code> et <code>new Function</code> sont rares, pour ne pas dire rarissimes, et tous les autres cas sont inutiles voire contre-productifs, au sens où ils entraînent des comportements inattendus et sources de bugs.</p>

<p>J&#8217;espère que cette petite balade à travers la sémantique des types natifs et les distinctions, souvent subtiles, entre les valeurs dites primitives et leurs équivalents objets vous aura intéressé, et qui sait, peut-être même éclairé sur des accrocs passés.</p>

<div data-upcoming-sessions="js-puissant" xstyle="display: none;">
  <h2>Envie d’en apprendre davantage&nbsp;?</h2>
  
  <p>Notre atelier <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> explore en profondeur tous les aspects techniques avancés du langage JavaScript lui-même.  Du bon usage de `new` à la programmation fonctionnelle en passant par les méthodes méconnues des types natifs et le fonctionnement des prototypes, cette formation JavaScript vous donne un gros coup de boost dans le développement de vos codes JS quels qu’ils soient.</p>

  <p>Prochaines sessions&nbsp;:</p>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sessions JavaScript début 2013]]></title>
    <link href="http://www.js-attitude.fr/2012/11/17/sessions-debut-2013/"/>
    <updated>2012-11-17T00:00:00+01:00</updated>
    <id>http://www.js-attitude.fr/2012/11/17/sessions-debut-2013</id>
    <content type="html"><![CDATA[<p>Voici enfin les dates des sessions inter-entreprises de janvier et février 2013 !</p>

<ol>
<li><a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> le 08/01 et le 19/02</li>
<li><a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> <strong>en format étendu 2 jours</strong> les 22 et 23/01</li>
<li><a href="http://www.js-attitude.fr/js-total/">JS Total</a> du 05 au 08/02 ! Vous étiez nombreux à attendre cette nouvelle date, la session de décembre 2012 étant complète.  Alors dépêchez-vous de vous inscrire pour ne pas arriver trop tard cette fois-ci !</li>
<li><a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a> le 26/02</li>
</ol>


<p>En revanche, en raison d&#8217;un nombre d&#8217;inscriptions véritablement trop faible d&#8217;une part, et de besoins intra-entreprises trop forts d&#8217;autre part, nous avons dû annuler préemptivement la session <a href="http://www.js-attitude.fr/coffee-guru/">Coffee Guru</a> du 19 au 21/12.</p>

<p>N&#8217;attendez pas ! Demandez rapidement vos conventions pour ces nouvelles dates !</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Mais qu'est-il arrivé à Prototype ?]]></title>
    <link href="http://www.js-attitude.fr/2012/10/06/mais-qu-est-il-arrive-a-prototype/"/>
    <updated>2012-10-06T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/10/06/mais-qu-est-il-arrive-a-prototype</id>
    <content type="html"><![CDATA[<p>En 2005, alors que Ajax devenait tendance et qu&#8217;on commençait à faire du JavaScript un peu costaud dans les pages web, il n&#8217;y avait pas encore de framework renommé.  Arrivé en premier et impressionant dès l&#8217;origine, Prototype est vite devenu le chouchou de la grande majorité des développeurs web.</p>

<p>En 2006 puis 2007, désormais doté d&#8217;une documentation solide et d&#8217;une équipe de développement (Prototype Core) compétente, motivée et très active, il était incontournable.</p>

<p>Avance rapide sur 2012&nbsp;: plus personne (ou presque) n&#8217;en parle.  On entend encore un peu parler de MooTools, Dojo, YUI…  Et le grand vainqueur est jQuery, ce framework à l&#8217;écosystème gigantesque et vivace, à tel point qu&#8217;on est obligé d&#8217;expliquer au plus grand nombre la différence entre jQuery et JavaScript.</p>

<p>Que s&#8217;est-il passé&nbsp;?</p>

<p>Ce petit article un peu nostalgique vous explique pourquoi Prototype a sombré et où il en est aujourd&#8217;hui.</p>

<!-- more -->


<h2>Full Disclaimer</h2>

<p>Je suis moi-même un ancien de Prototype Core.  En 2006, avec <a href="http://www.amazon.fr/Bien-d%C3%A9velopper-pour-Web-2-0/dp/2212123914">Bien Développer pour le Web 2.0</a>, je produisais la première documentation exhaustive du framework, alors en version 1.4.</p>

<p>Durant l&#8217;hiver, j&#8217;étais l&#8217;un des trois co-auteurs du <a href="http://prototypejs.org/">site officiel</a> de documentation, et en janvier 2007 je rejoignais le noyau des développeurs pour produire, au fil des mois, les versions 1.5, 1.5.1 (qui était absolument géniale à l&#8217;époque) puis 1.6.  En 2008, je publiais la référence, <a href="http://pragprog.com/book/cppsu/prototype-and-script-aculo-us">Prototype and script.aculo.us</a>, chez les Pragmatic Programmers.</p>

<h2>2005–2008&nbsp;: l&#8217;âge d&#8217;or</h2>

<p>C&#8217;était une période dorée.  L&#8217;équipe était petite mais très active&nbsp;: Sam Stephenson, Andrew Dupont, Tobie Langel, Mislav Marohnić, Juriy Zaytsev et Thomas Fuchs, le créateur de script.aculo.us, plus votre serviteur.</p>

<p>On bossait beaucoup et ça se voyait, Prototype dominait complètement le marché des bibliothèques médianes, qui simplifiaient Ajax et le DOM mais aussi la création d&#8217;algorithmes compliqués et de systèmes de classes.</p>

<h2>La décroissance</h2>

<p>Et puis, presque du jour au lendemain, jQuery a pris presque toute la place.  Les raisons sont multiples, mais ses forces principales étaient évidentes&nbsp;:</p>

<ul>
<li>Une cible plus étroitement définie mais majoritaire sur le marché&nbsp;: les intégrateurs HTML/CSS qui ne veulent pas apprendre JavaScript trop en profondeur&nbsp;: ils veulent «&nbsp;juste&nbsp;» des effets visuels, des animations simples et de l&#8217;Ajax simplifié.</li>
<li>Une syntaxe facile et laxiste, triviale à apprendre, ne demandant que très peu d&#8217;efforts et de rigueur</li>
<li>Une équipe volumineuse</li>
<li>Une vraie force de frappe marketing, avec des tonnes de docs, tutorials, meetups, événements communautaires puis conférences, bouquins…</li>
</ul>


<p>Alors que jQuery ne cessait de grandir, épaulée par le statut Mozillien de John Resig et une forte attention portée à sa communauté, pour atteindre rapidement de très nombreuses personnes dédiées à temps plein, Prototype, lui, voyait son équipe se réduire comme peau de chagrin.</p>

<p>Nous avions tous un boulot à temps plein à côté, nous étions peu nombreux, nous nous concentrions sur le code et n&#8217;accordions que très peu de temps à la visibilité de Prototype.  Et jQuery l&#8217;a éclipsé.</p>

<p>Encore aujourd&#8217;hui, beaucoup de gens qui sont «&nbsp;tombés dans Prototype&nbsp;» à l&#8217;époque continuent à l&#8217;utiliser, tout en connaissant aussi jQuery.  Ils aiment Prototype pour son API claire, cohérente et élégante, ses nombreuses fonctions orientées algorithmes et programmation fonctionnelle (avec jQuery, il faut complémenter par <a href="http://underscorejs.org/">Underscore.js</a>, très fortement inspiré de Prototype, pour obtenir un équivalent).</p>

<p>Mais Prototype, aujourd&#8217;hui, c&#8217;est quelques jours par mois, voire par trimestre, du seul porteur du flambeau qui reste, le vaillant Andrew Dupont.  Sa détermination sans faille me touche et m&#8217;émeut&nbsp;; mais le projet n&#8217;en est pas moins dans un coma léger, parfois même profond.</p>

<h2>Des utilisateurs fidèles</h2>

<p>J&#8217;ai moi-même arrêté de travailler à Prototype il y a presque 4 ans.  Jusqu&#8217;à cet été cependant, il restait ma bibliothèque de choix pour tous mes développements front.</p>

<p>Quand j’utilise jQuery, si j&#8217;apprécie la complétude de son offre Ajax/JSONP et certains aspects de son offre DOM, je peste contre les nombreux pièges inhérents au design de son API, pièges souvent silencieux et sournois à l&#8217;exécution.</p>

<p>Et j&#8217;ai, évidemment, toujours Underscore.js en complément, car je ne pourrais me passer d&#8217;un <code>each</code> raisonnable, de <code>filter</code>, <code>inject</code>, <code>flatten</code>, <code>without</code> et j&#8217;en passe.</p>

<h2>De la gratitude</h2>

<p>Alors oui, Prototype est pratiquement mort, malgré la persistence éminemment louable d&#8217;Andrew.  Mais j&#8217;aimerais qu&#8217;on se rappelle que Prototype a été <em>le premier</em>.  Sam a <em>inventé</em> ce positionnement de bibliothèque, a pondu des API dont l&#8217;influence se fait sentir partout, de ES5 à Underscore.js en passant par jQuery lui-même, que John a clairement dit avoir lancé «&nbsp;parce [qu&#8217;il] n&#8217;était pas totalement en phase avec Prototype&nbsp;».</p>

<p>Autour de la 1.5, on a fait des prouesses pour les premiers outils de type <code>$$</code>, en implémentant l&#8217;intégralité des sélecteurs CSS3 à la fois en DOM Level 3 XPath et en parcours classique.</p>

<p>Prototype a permis des merveilles dès 2005, et a connu une sacrée gloire pendant plusieurs années.</p>

<p>Je lui dis un immense merci, et à mon sens, les web devs du monde entier, y compris ceux qui ne l&#8217;ont jamais utilisé, ont eux aussi cette dette de gratitude.</p>

<p>Et le web continue…</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[JavaScript n'a rien à voir avec Java : petite histoire d'un marketing malheureux]]></title>
    <link href="http://www.js-attitude.fr/2012/09/17/javascript-n-a-rien-a-voir-avec-java/"/>
    <updated>2012-09-17T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/09/17/javascript-n-a-rien-a-voir-avec-java</id>
    <content type="html"><![CDATA[<p>Nous les développeurs JS, on grince souvent des dents lorsqu&#8217;on tombe sur quelqu&#8217;un qui, en parfaite ignorance, met dans le même sac JavaScript et Java.  Nous demande une «&nbsp;formation Java&nbsp;», ou nous classe comme «&nbsp;développeur Java&nbsp;».</p>

<p>Ayant moi-même pondu quelques millions de lignes (littéralement, mais en Java ça n&#8217;est pas si impressionnant que ça) de Java et J2EE (ça ne s&#8217;appelait pas encore Java EE&nbsp;; je me fadais les premières versions des EJB, JSP et servlets…), dans JBuilder, Eclipse, NetBeans et IDEA, je sais pourquoi j&#8217;ai fui cet univers et pourquoi JavaScript n&#8217;a <strong>strictement rien à voir</strong>.</p>

<p>Seulement voilà, le nommage prête à confusion, c&#8217;est un fait.  Au mieux, on nous demande «&nbsp;c&#8217;est quoi la différence entre Java et JavaScript&nbsp;?&nbsp;»  Ce à quoi j&#8217;aime à répondre «&nbsp;la même qu&#8217;entre l&#8217;or et l&#8217;ordinateur&nbsp;»&nbsp;: à part le préfixe phonétique, la rapport est plutôt ténu…</p>

<p>Pour ceux qui aimeraient comprendre la petite histoire derrière la génèse de JavaScript et ce nommage foireux, permettez-moi de vous éclairer…</p>

<!-- more -->


<h2>Le besoin d&#8217;origine et le cœur de la différence</h2>

<p>Début 1995, <strong>Netscape</strong> domine le marché du web en général, fournissant tant des logiciels serveurs que le navigateur alors le plus populaire, Netscape Navigator.  Ils viennent de lancer un partenariat avec <strong>Sun Microsystems</strong> pour exploiter leur nouveau langage et sa VM multi-plateforme, Java, tant au sein du navigateur (pour fournir une UI riche portable) que côté serveur (pour fournir le cœur d&#8217;applications accessibles <em>via</em> le web, au moyen d&#8217;un simple navigateur).</p>

<p>C&#8217;est une offre impressionnante, en concurrence directe avec Microsoft, qui commence à peine à accepter le fait que le web est là pour durer et qu&#8217;il constitue le prochain pivot technologique majeur.</p>

<p>Toutefois, Java est perçu par Sun et Netscape comme un langage de professionnels, peu adapté à une utilisation simple dans le cadre de pages web (on ne parle pas encore d&#8217;applis web, il faudra attendre 10 ans et l&#8217;avènement d&#8217;Ajax).  Java est en quelque sorte le concurrent du Visual C++ de Microsoft, de ce point de vue.  Il lui faut un langage compagnon plus simple d&#8217;approche, plus facile d&#8217;emploi pour les néophytes ou développeurs débutants, qui soit, si l’on veut, l&#8217;équivalent de Visual Basic.  Facile à prendre en main, facile à imbriquer dans une page ou ailleurs.</p>

<p>C&#8217;est à <a href="http://fr.wikipedia.org/wiki/Brendan_Eich">Brendan Eich</a>, gourou technique chez Netscape et futur CTO de Mozilla, qu&#8217;est revenue la tâche de créer ce langage «&nbsp;compagnon&nbsp;» de toutes pièces.</p>

<p>Ceci dit, on exige également que les deux soient bien différenciés, au sens où les développeurs potentiels doivent sentir que le nouveau langage est «&nbsp;dans le style Java&nbsp;» mais est moins puissant.  Comme l&#8217;a expliqué Brendan dans une interview&nbsp;:</p>

<blockquote><p>JS devait «&nbsp;ressembler à Java&nbsp;», mais en moins avancé, [il devait] être le petit frère simplet de Java, son partenaire-otage.  Et par-dessus le marché, je n’avais que dix jours pour pondre ça, ou on se retrouverait avec un truc pire que JS.</p><footer><strong>Brendan Eich</strong></footer></blockquote>


<p>JavaScript devait donc rester conscient des spécificités de la syntaxe de Java (JS 1.0 avait tous les mots-clés de Java réservés, et ses types standard copient souvent les conventions du JDK, par exemple autour de <code>Math</code> et <code>Date</code>), mais il devait aussi s&#8217;abstenir d&#8217;utiliser la syntaxe orientée-objet du langage, à une époque ou la POO (Programmation Orientée Objet) était encore considérée comme un sujet réservé aux professionnels…</p>

<p><strong>Brendan ne voulait pas pondre un langage diminué, mais devait trouver des ruses pour y glisser assez de puissance sans que celle-ci soit immédiatement visible au profane.</strong>  Le langage devait rester simple et léger en apparence, tout en ayant assez de sophistication pour que des développeurs avancés soient à même d’en tirer des applications puissantes.</p>

<p>Si les deux langages appartiennent à une famille syntaxique «&nbsp;de type C&nbsp;» (syntaxe des identifiants, accolades, opérateurs principaux, structures de contrôle…), ils ont des sémantiques extrêmement différentes.  La philosophie de JavaScript est très fortement inspirée de langages objet ou fonctionnels «&nbsp;purs&nbsp;», au premier rang desquels <a href="http://en.wikipedia.org/wiki/Self_(programming_language)">Self</a> et <a href="http://en.wikipedia.org/wiki/Scheme_(programming_language)">Scheme</a>, mais aussi certains aspects de <a href="http://en.wikipedia.org/wiki/Smalltalk">SmallTalk</a> et <a href="http://en.wikipedia.org/wiki/Lisp_(programming_language)">LISP</a>.</p>

<p>Java est un langage compilé, statique (chaque variable est typée explicitement) et doté d&#8217;un typage fort (le type déclaré contraint les valeurs de façon étroite, et aucune conversion implicite n&#8217;est mise en place), là où JavaScript est interprété et <strong>dynamique</strong> avec un <strong>typage plus léger</strong> (d&#8217;où la distinction entre <code>==</code> et <code>===</code>, similaire à celle de PHP).</p>

<p>En Java, tout code existe à l&#8217;intérieur d&#8217;une classe.  JavaScript ne l&#8217;exige pas.</p>

<p>Java, malgré près d&#8217;une décennie de débat stérile, n&#8217;a toujours pas de <a href="http://en.wikipedia.org/wiki/First-class_function">fonctions de premier ordre</a>.  JavaScript a des fonctions de premier ordre et, partant, des <a href="http://en.wikipedia.org/wiki/Higher-order_function">fonctions d&#8217;ordre supérieur</a>.</p>

<p>Java utilise un modèle d&#8217;héritage «&nbsp;classique&nbsp;», mono-parent, basé sur l&#8217;héritage de classes.  JavaScript est basé sur les <strong>prototypes</strong> et autorise plusieurs paradigmes de programmation, notamment les styles orienté-objet, impératif et <strong>fonctionnel</strong> (largement inspiré par Scheme).</p>

<p>Vous le voyez, les deux langages sont extrêmement différents, à un niveau pratique comme à un niveau fondamental, philosophique.</p>

<h2>Les noms de départ</h2>

<p>JavaScript était développé sous le nom de code <strong>Mocha</strong>, son nom officiel prévu étant <strong>LiveScript</strong>.  C&#8217;était pourtant pas mal ce nom, vous ne trouvez pas&nbsp;?  Microsoft n&#8217;avait pas encore collé une connotation négative à «&nbsp;Live&nbsp;» à l&#8217;époque…  Et d&#8217;ailleurs, dans les deux premières versions beta de Netscape Navigator 2.0, en septembre 1995, on trouve en effet LiveScript.</p>

<h2>La décision marketing pourrie</h2>

<p>Hélas, trois fois hélas, les marketeux ont voulu insister sur le rôle «&nbsp;collaboratif&nbsp;» de ce langage vis-à-vis de Java et ses applets, et tenter probablement de récupérer une partie du prestige issu du marketing de Sun autour de Java.  Du coup, à partir de Netscape Navigator 2.0ß3, Brendan a dû le renommer JavaScript.</p>

<p><em>Et la confusion naquit.</em></p>

<p>Peu après, Netscape voulut, à juste titre, faire bénéficier JavaScript d&#8217;un processus formel de standardisation.  IETF, ISO et le jeune W3C posaient chacun des problèmes distincts dans cette optique, de sorte qu&#8217;au final c&#8217;est l&#8217;ECMA (<em>European Computer Manufacturers Association</em>), un organisme de standardisation européen, qui a récupéré le bébé.  Et on a vu apparaître la première édition du standard ECMA-262, pour le langage ECMAScript, qui est en pratique essentiellement utilisé en tant que JavaScript.</p>

<p>La 3ème édition (ES3) constitue le socle de la version la plus répandue/utilisée du langage (à peu près équivalente à JavaScript 1.5). La 4ème est morte-née, et la 5ème (ES5), désormais implémentée dans tous les navigateurs modernes, sert de socle aux applis web modernes et à JS côté serveur (avec Node.js notamment).</p>

<h2>Ironie du sort</h2>

<p>Ce qui à mon sens est assez amusant dans cette affaire, c&#8217;est que JavaScript est, finalement, disponible <em>de base</em> sur davantage de plates-formes et périphériques que Java, aujourd&#8217;hui. Même si l&#8217;explosion d&#8217;Android a fortement relancé le déploiement de Java, qui s&#8217;enorgueillit de «&nbsp;plusieurs milliards de périphériques installés&nbsp;» (comme en a longtemps témoigné la grande bannière Oracle/Sun à l&#8217;aéroport Charles de Gaulle terminal 1…), Java n&#8217;est pas tellement déployé sur d&#8217;autres plates-formes mobiles, et n&#8217;est pas non plus automatiquement présent sur toutes les plates-formes desktop.</p>

<p>Mais allez trouver un seul desktop, laptop, smartphone, tablette ou liseuse qui n&#8217;ait pas une <em>runtime</em> JavaScript installée—et s&#8217;en serve intensivement&nbsp;! Dans certains cas, comme webOS et maintenant Firefox Mobile OS, JavaScript est au cœur-même de la plate-forme, constituant sa clé de voûte. Même sur iOS, Android ou les Blackberry récents, la tendance forte des <em>mobile web apps</em> repose très lourdement sur JavaScript. Petit à petit, les technologies collectivement appelées «&nbsp;HTML5&nbsp;» remplacent ce pourquoi on avait encore recours aux applets ou, plus souvent, à Flash.</p>

<p>La couche serveur connaît elle aussi, depuis plus de 2 ans maintenant, une explosion de JavaScript comme langage de développement, avec des résultats impressionnants. La course à la performance des <em>runtimes</em> JavaScript (V8, cœur de Node.js, affiche des performances bluffantes), couplée au modèle de développement traditionnellement événementiel de JavaScript, qui permet d&#8217;assurer de fortes charges sans coût linéaire, y sont pour beaucoup.</p>

<p>Je souris en pensant que JavaScript, nommé ainsi parce qu&#8217;il essayait de «&nbsp;faire sérieux&nbsp;» et tirer parti des nues marketing auxquelles on portait Java, a déjà, je trouve, supplanté ce dernier en termes de présence sur les marchés qui comptent.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Le nombre qui s'incrémente tout seul]]></title>
    <link href="http://www.js-attitude.fr/2012/09/13/le-nombre-qui-s-incremente-tout-seul/"/>
    <updated>2012-09-13T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/09/13/le-nombre-qui-s-incremente-tout-seul</id>
    <content type="html"><![CDATA[<p>Les nombres sont parfois trompeurs, en JavaScript comme ailleurs.  Ouvrez donc une console JavaScript et tentez les expressions suivantes&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="mi">1234567890</span>          <span class="c1">// =&gt; 1234567890</span>
</span><span class='line'><span class="mi">999999999999999</span>     <span class="c1">// =&gt; 999999999999999</span>
</span><span class='line'><span class="mi">9999999999999999</span>    <span class="c1">// =&gt; 10000000000000000 -- WTF?!</span>
</span></code></pre></td></tr></table></div></figure>


<p>Voyons ensemble la baleine qui se cache sous ce gravier…</p>

<!-- more -->


<p>Mais quelle magie obscure fait que 999999999999999 se comporte bien, mais pas 9999999999999999&nbsp;?</p>

<p>Comme dans de très nombreux langages, nous voilà pris au piège du standard <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE-754</a>, datant de 1985 (bientôt 30 ans…), qui gouverne la représentation 64-bit des nombres flottants.  Vous retrouverez ce souci dans C, C++, Java, PHP, et pour autant que je sache, .NET (C#, VB, etc.) et ColdFusion…  Mais uniquement sur les nombres flottants.  Les nombres entiers 64-bit vont bien au-delà.</p>

<p>Seulement voilà, JavaScript ne différencie pas entiers et flottants.  Le type <code>Number</code> est forcément flottant, c&#8217;est pourquoi en JavaScript <code>5 / 2 === 2.5</code>, alors que les opérandes semblent «&nbsp;entiers&nbsp;».</p>

<p>IEEE-754 prévoit une <em>double précision</em> (d&#8217;où le nom usuel du type associé dans de nombreux langages&nbsp;: <code>double</code>) de 15 chiffres.  Au total (avant et après la virgule éventuelle).  Dès qu&#8217;on dépasse ce nombre de chiffres, la représentation mémoire utilisée commence à faire des arrondis.  Et plus on a de chiffres voulus, plus l&#8217;arrondi est brutal&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="mi">12345678901234567890</span> <span class="c1">// =&gt; 12345678901234567000</span>
</span></code></pre></td></tr></table></div></figure>


<p>Au passage, et pour le plaisir, notez que l&#8217;approximation n&#8217;a pas lieu que sur des très hautes valeurs. Si on tombe sur des valeurs qui ne sont pas représentables pile-poil par IEEE-754, on obtient des trucs comiques&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="mf">0.3</span>         <span class="c1">// =&gt; 0.3</span>
</span><span class='line'><span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span>   <span class="c1">// =&gt; 0.30000000000000004 !</span>
</span></code></pre></td></tr></table></div></figure>


<p>Et oui, comme pour le statut <em><a href="http://www.js-attitude.fr/2012/09/10/truthy-ou-falsy-en-javascript/">truthy</a></em>, la valeur seule ne suffit pas à garantir le bon fonctionnement&nbsp;: la façon d&#8217;y arriver est tout aussi importante.</p>

<p>Ici, il se trouve que 0.1 est représenté, en interne, par une valeur retranscrite en 0.10000000000000002.  Et de même, 0.2 par 0.20000000000000002.  Du coup, la somme aboutit à un résultat… étonnant&nbsp;!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Truthy ou falsy : quand est-on dans le vrai en JavaScript ?]]></title>
    <link href="http://www.js-attitude.fr/2012/09/10/truthy-ou-falsy-en-javascript/"/>
    <updated>2012-09-10T00:00:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/09/10/truthy-ou-falsy-en-javascript</id>
    <content type="html"><![CDATA[<p>Lorsqu&#8217;on vient à JavaScript, il est tentant de recourir à de bons vieux motifs de code hérités des autres langages que l&#8217;on pratique.  Un cas classique est l&#8217;abréviation de conditions en se reposant sur les <strong>« équivalents booléens »</strong> des valeurs.  Le danger, c&#8217;est que JavaScript a beaucoup plus de valeurs <strong>falsy</strong> que les autres langages, et utilise des <strong>protocoles de conversion implicite</strong> parfois surprenants.</p>

<p>Dans cet article, nous allons explorer ensemble quelles valeurs sont <em>falsy</em>, et donc lesquelles sont <em>truthy</em>, mais aussi l&#8217;impact que ça a sur de nombreux motifs de code courants, avec les <strong>pièges</strong> que ça peut poser.</p>

<!-- more -->


<h2><em>Truthy</em> et <em>falsy</em></h2>

<p>Dans un langage de programmation, on dit qu&#8217;une valeur est <em>truthy</em> si, considérée dans un contexte booléen (le plus souvent comme seul composant d&#8217;une condition, ou comme opérande d&#8217;un opérateur booléen tel que <code>&amp;&amp;</code> ou <code>||</code>), elle équivaut à <code>true</code>.</p>

<p>On dit que le <em>protocole de conversion implicite</em> de son type vers <code>Boolean</code> donne <code>true</code>.  En JavaScript, ce protocole spécifique est régi, pour JavaScript «&nbsp;classique&nbsp;» (ECMAScript 3e édition) par la section 9.3 de la spécification (ECMA-262).  Par complément, toute valeur dont la conversion ne donne pas <code>true</code> donne nécessairement <code>false</code>.</p>

<p>La spécification indique clairement que les types Undefined et Null équivalent toujours à <code>false</code>.  Toute chaîne vide (longueur zéro) également.  Côté nombres, les zéros (positif ou négatif) et <code>NaN</code> équivalent eux aussi à <code>false</code>.  En revanche, n&#8217;importe quel autre objet (dont les tableaux et objets litéraux, même vides) équivaudra à <code>true</code>.</p>

<p>Ces règles semblent assez simples, même s&#8217;il peut être surprenant de voir que <code>''</code> est équivalent à <code>false</code> (mais que <code>new Boolean(false)</code>, étant un objet, est équivalent à <code>true</code>, un magnifique WTF).  Toutefois, n&#8217;arrêtez pas là votre lecture, car dans divers cas «&nbsp;piégeux&nbsp;» les conversions implicites s&#8217;enchaînent sur une même valeur et donnent un résultat surprenant&nbsp;!  Nous avons vu les règles de base, mais attendez la suite…</p>

<h2>Impact sur les motifs de code usuels</h2>

<p>Examinons tour à tour les principaux cas où l&#8217;emploi booléen d&#8217;une valeur autre se présente dans du code JavaScript usuel.</p>

<h3>Boucle numérique «&nbsp;façon C&nbsp;»</h3>

<p>Une tentation courante consiste à reproduire les boucles numériques du C.  Par exemple&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span><span class='line'><span class="k">while</span> <span class="p">(</span><span class="nx">count</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// votre traitement ici</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ou encore&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">index</span><span class="o">--</span><span class="p">;</span> <span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// votre traitement ici</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Pas de problème particulier sur cette boucle, en tout cas vis-à-vis de son équivalent C.</p>

<p>Le même risque potentiel existe, naturellement&nbsp;: si par mégarde le contenu de la boucle <em>modifie le compteur</em>, et que du coup celui-ci «&nbsp;saute&nbsp;» zéro ou est compensé dans son mouvement normal, cette boucle n&#8217;aura pas de fin (en C, elle finirait par un overflow/underflow, mais en JS, qui n&#8217;a que des nombres flottants, la fin est si loin qu&#8217;en pratique on ne patientera jamais assez longtemps, sans parler des bugs causés par le dépassement de limite).</p>

<p>Le piège est notamment là en JS, qui n&#8217;a pas de variables de blocs (sauf à disposer d&#8217;un JS garanti suffisamment récent pour pouvoir utiliser l&#8217;instruction <code>let</code>)&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Attention, ce code n&#39;a pas de fin !</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">count</span><span class="o">--</span><span class="p">;</span> <span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">count</span><span class="p">);</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">count</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="o">++</span><span class="nx">count</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">count</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ahem…</p>

<h3>Tester la présence d&#8217;un texte</h3>

<p>Attention ici à la notion de «&nbsp;présence&nbsp;».  Si seul un texte absolument vide (longueur zéro) vous ennuie, pas de souci, c&#8217;est bien la sémantique d&#8217;origine&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Supposons un champ &lt;input type=&quot;text&quot; id=&quot;firstName&quot; value=&quot;&quot;&gt;</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#firstName&#39;</span><span class="p">).</span><span class="nx">val</span><span class="p">())</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Ce code ne sera pas déclenché</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Mais si vous voulez un texte <em>non-blank</em>, c&#8217;est-à-dire contenant autre chose que du <em>whitespace</em>, il faudra préférer une regex (<a href="http://www.js-attitude.fr/2012/08/13/enfin-maitriser-les-expressions-rationnelles">hein&nbsp;?!</a>) pour vérifier le contenu du texte&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Supposons un champ &lt;input type=&quot;text&quot; id=&quot;firstName&quot; value=&quot;   &quot;&gt;</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#firstName&#39;</span><span class="p">).</span><span class="nx">val</span><span class="p">())</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Ce code SERA déclenché (à tort, a priori)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">BLANK_TEXT</span> <span class="o">=</span> <span class="sr">/^\s*$/</span><span class="p">;</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">BLANK_TEXT</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#firstName&#39;</span><span class="p">).</span><span class="nx">val</span><span class="p">()))</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Ce code ne sera pas déclenché</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Alternativement :</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">PRESENT_TEXT</span> <span class="o">=</span> <span class="sr">/\S/</span><span class="p">;</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">PRESENT_TEXT</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#firstName&#39;</span><span class="p">).</span><span class="nx">val</span><span class="p">()))</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Ce code ne sera pas déclenché</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Tester la présence de nœuds du DOM</h3>

<p>Si <code>getElementById</code> renvoie bien <code>null</code> s&#8217;il ne trouve pas l&#8217;élément d&#8217;id indiqué, l&#8217;immense majorité d&#8217;entre nous utilisons une bibliothèque JavaScript pour interagir avec le DOM.  La plupart du temps, nous utilisons une API basée sur jQuery, qu&#8217;il s&#8217;agisse de jQuery lui-même, Zepto ou encore Ender.  Du coup, ce que nous avons sous la main se comporte en fait comme un tableau, et n&#8217;est donc <strong>jamais équivalent <code>false</code></strong>&nbsp;!</p>

<p>Voyez plutôt&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#idNotFound&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Ce code sera TOUJOURS exécuté !</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>C&#8217;est la raison pour laquelle on voit tant de code comme celui-ci&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#idNotFound&#39;</span><span class="p">).</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Si la longueur est non-nulle (élément trouvé) ce code sera exécuté</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Paramètre doté d&#8217;une valeur par défaut</h3>

<p>En <a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a>, c&#8217;est trivial à gérer, mais en JS pur c&#8217;est un peu plus compliqué.  Tout dépend en fait des <strong>valeurs considérées comme valides pour l&#8217;argument</strong>.</p>

<p>Si aucune valeur <em>falsy</em> n&#8217;est valide, on est tranquille et on peut juste utiliser le <code>||</code> (OU logique)&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">earnMoney</span><span class="p">(</span><span class="nx">luckyGuy</span><span class="p">,</span> <span class="nx">howMuch</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">howMuch</span> <span class="o">=</span> <span class="nx">howMuch</span> <span class="o">||</span> <span class="mi">10000</span><span class="p">;</span>
</span><span class='line'>  <span class="c1">// Ou parfois : howMuch || howMuch = 10000; // Les goûts et les couleurs…</span>
</span><span class='line'>  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">luckyGuy</span> <span class="o">+</span> <span class="s1">&#39; gagne &#39;</span> <span class="o">+</span> <span class="nx">howMuch</span> <span class="o">+</span> <span class="s1">&#39;€&#39;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ici, on considère par exemple que <code>howMuch</code> à zéro, <code>NaN</code>, chaîne vide, et simplement non passé (<code>undefined</code>) ne constituerait pas une valeur acceptable.  Il n&#8217;est donc pas possible d&#8217;appeler <code>earnMoney</code> avec un deuxième argument à zéro&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;John&#39;</span><span class="p">)</span>           <span class="c1">// &#39;John gagne 10000€&#39;</span>
</span><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;Nicolas&#39;</span><span class="p">,</span> <span class="mi">1000</span><span class="p">)</span>  <span class="c1">// &#39;Nicolas gagne 1000€&#39;</span>
</span><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;Yannick&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>    <span class="c1">// &#39;Yannick gagne 10000€&#39; !</span>
</span></code></pre></td></tr></table></div></figure>


<p>Lorsque des valeurs <em>falsy</em> sont acceptables, il vous appartient de tester plus efficacement.  Par exemple, on pourrait refuser toute valeur négative ou nulle, et gérer évidemment le cas &#8220;argument manquant&#8221;&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">earnMoney</span><span class="p">(</span><span class="nx">luckyGuy</span><span class="p">,</span> <span class="nx">howMuch</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="s1">&#39;undefined&#39;</span> <span class="o">==</span> <span class="k">typeof</span> <span class="nx">howMuch</span> <span class="o">||</span> <span class="o">+</span><span class="nx">howMuch</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
</span><span class='line'>    <span class="nx">howMuch</span> <span class="o">=</span> <span class="mi">10000</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">luckyGuy</span> <span class="o">+</span> <span class="s1">&#39; gagne &#39;</span> <span class="o">+</span> <span class="nx">howMuch</span> <span class="o">+</span> <span class="s1">&#39;€&#39;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>(Notez au passage le recours à l&#8217;opérateur unaire préfixe <code>+</code>, qui force le protocole de conversion explicite <em>ToNumber</em> (conversion vers un nombre), et refusera notamment toute valeur textuelle ne constituant pas intégralement un nombre décimal valide.  Cette technique est en ce sens supérieure à <code>parseFloat</code>.)</p>

<p>Ici on a bien le comportement souhaité&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;John&#39;</span><span class="p">)</span>            <span class="c1">// &#39;John gagne 10000€&#39;</span>
</span><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;Nicolas&#39;</span><span class="p">,</span> <span class="mi">1000</span><span class="p">)</span>   <span class="c1">// &#39;Nicolas gagne 1000€&#39;</span>
</span><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;Yannick&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>     <span class="c1">// &#39;Yannick gagne 0€&#39;</span>
</span><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;Matthieu&#39;</span><span class="p">,</span> <span class="o">-</span><span class="mi">10</span><span class="p">);</span>  <span class="c1">// &#39;Matthieu gagne 10000€&#39;</span>
</span><span class='line'><span class="nx">earnMoney</span><span class="p">(</span><span class="s1">&#39;Marie&#39;</span><span class="p">,</span> <span class="s1">&#39;10foo&#39;</span><span class="p">);</span> <span class="c1">// &#39;Marie gagne 10000€&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Pièges des priorités de conversion</h2>

<p>Les conversions implicites peuvent être problématiques.  Elles sont déclenchées automatiquement sur toute condition mono-composant et opération binaire autre que <code>===</code> et <code>!==</code> (qui exigent une identité de type, en plus d&#8217;une identité de valeur, et sont recommandées par défaut pour toute comparaison, afin de réduire les risques).</p>

<p>Voyez plutôt&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;  &#39;</span> <span class="o">==</span> <span class="kc">false</span><span class="p">)</span>     <span class="c1">// true</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="s1">&#39;  &#39;</span><span class="p">)</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;mais…&#39;</span><span class="p">)</span> <span class="c1">// &#39;mais…&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">([]</span> <span class="o">==</span> <span class="kc">false</span><span class="p">)</span>     <span class="c1">// true</span>
</span><span class='line'><span class="k">if</span> <span class="p">([])</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;mais…&#39;</span><span class="p">)</span> <span class="c1">// &#39;mais…&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Voilà qui est fort étrange (et y&#8217;en a encore plein des comme ça).  En fait, il ne s&#8217;agit pas ici uniquement de la conversion implicite de <code>String</code> ou <code>Array</code> en booléens, qui n&#8217;est utilisé que dans les <code>if</code> du code ci-dessus.  Il s&#8217;agit aussi de la spécification de l&#8217;opérateur <code>==</code>, telle que décrite au paragraphe 11.9.3 de ECMA-262 (3ème édition), la spécification de JavaScript.  Déroulons les parties pertinentes de l&#8217;algo utilisé par le moteur JS pour le premier cas, <code>'  ' == false</code>&nbsp;:</p>

<ol>
<li>On a affaire à un non-booléen comparé à un booléen : on compare <code>'  '</code> à <code>ToNumber(false)</code></li>
<li>La conversion implicite numérique d&#8217;un booléen vaut <code>+0</code> (<code>0</code>, quoi…) pour <code>false</code>, on a donc <code>'  ' == 0</code></li>
<li>On compare une <code>String</code> avec un <code>Number</code> : on compare <code>ToNumber('  ')</code> à <code>0</code></li>
<li>La conversion implicite numérique d&#8217;une chaîne de caractère constitué uniquement de <em>whitespace</em> vaut (section 9.3.1) <code>0</code>, on compare donc <code>0 == 0</code>, ce qui vaut évidemment <code>true</code>.</li>
</ol>


<p>En revanche, dans le cas du <code>if</code>, on applique immédiatement <code>ToBoolean('  ')</code>, et comme la chaîne n&#8217;est pas vide, on obtient <code>true</code>.</p>

<p>Subtil&nbsp;!  Et, oui, un peu foireux côté spécification…</p>

<p>Pour le second cas, <code>[] == false</code>, on obtient le même type de déroulé, si ce n&#8217;est qu&#8217;à l&#8217;étape 3 on atteint <code>Object</code> (<code>Array</code> est un type descendant) avec un <code>Number</code>, ce qui déclenche <code>ToPrimitive([])</code>, décrit à la section 9.1.  Celle-ci nous dit qu&#8217;on utilise alors la propriété système <code>[[DefaultValue]]</code> de l’objet, telle que décrite à la section 8.6.2.6 (remarquez combien ECMA-262 est une spécification <em>pour les implémenteurs</em>, et non pour les <em>développeurs</em>, et comme on s&#8217;y emmêle les pieds à coups de références croisées comme dans un code juridique).  Les renvois continuent, jusqu&#8217;à ce qu&#8217;on se rende compte qu&#8217;on aboutit à une conversion numérique aboutissant, faute d&#8217;élément unique exploitable dans le tableau, à zéro.</p>

<p>Bref, faites attention lorsque vous exploitez une valeur non booléenne comme booléenne&nbsp;: il n&#8217;y a pas <em>que</em> la conversion implicite du type d&#8217;origine, mais aussi, pour une expression avec opérateurs, les algorithmes de conversion d&#8217;opérande définis pour ces opérateurs.  Et les deux peuvent, en effet, se contredire.</p>

<div data-upcoming-sessions="js-puissant" xstyle="display: none;">
  <h2>Envie d’en apprendre davantage&nbsp;?</h2>
  
  <p>Notre atelier <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> explore en profondeur tous les aspects techniques avancés du langage JavaScript lui-même.  De la <em>truthiness</em> à la programmation fonctionnelle en passant par les méthodes méconnues des types natifs et le fonctionnement des prototypes, cette formation JavaScript vous donne un gros coup de boost dans le développement de vos codes JS quels qu’ils soient.</p>

  <p>Prochaines sessions&nbsp;:</p>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[3 nouveaux ateliers et 7 sessions 2012 pour JS Attitude]]></title>
    <link href="http://www.js-attitude.fr/2012/08/26/nouvelles-sessions-js-attitude/"/>
    <updated>2012-08-26T22:40:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/08/26/nouvelles-sessions-js-attitude</id>
    <content type="html"><![CDATA[<p>À partir de la semaine du 19/11/2012, les formations Attitude vont passer à la vitesse supérieure.  Dans la pratique, cela signifie&nbsp;:</p>

<ul>
<li>De nouveaux ateliers</li>
<li>(Beaucoup) plus de dates et un lieu de formation au top</li>
<li>Plus d&#8217;articles didactiques sur le site</li>
<li>Une nouvelle plate-forme intégrée pour présenter les formations, gérer les inscriptions, permettre les évaluations et commentaires, accéder aux ressources pédagogiques, demander des conventions de formation, etc.</li>
</ul>


<!-- more -->


<h2>De nouveaux ateliers</h2>

<p>Comme annoncé il y a quelques semaines sur Twitter, l&#8217;automne-hiver 2012 voit l&#8217;apparition de <strong>3 nouveaux ateliers</strong> au catalogue JS Attitude&nbsp;:</p>

<ul>
<li><a href="http://www.js-attitude.fr/js-total/">JS Total</a> est une <strong>énorme tuerie</strong> qui combine, sur <strong>4 jours</strong> consécutifs, tous les savoir-faire des autres formations, dans un contexte plus intégré&nbsp;: du langage lui-même à l&#8217;optimisation du déploiement et des performances en passant par le MVC, les Web Sockets, les tests automatisés et la documentation. La première session aura lieu du 11 au 14 décembre.</li>
<li><a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a> est un atelier de formation d&#8217;une journée permettant de découvrir cette extraordinaire façon de développer du JavaScript qualitatif et performant.  Vous pourrez le tester dès le 18 décembre.</li>
<li><a href="http://www.js-attitude.fr/coffee-guru/">Coffee Guru</a> combine l&#8217;atelier CoffeeScript et <a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> v3, mais ce dernier est allongé sur 2 jours au lieu d’un, et 100% en CoffeeScript, pour permettre aux stagiaires de passer davantage de temps en exercice personnel et leur donner l&#8217;occasion de s&#8217;approprier ainsi davantage l&#8217;ensemble des savoirs dispensés.  Première session de <strong>3 jours</strong> du 19 au 21 décembre prochains.</li>
</ul>


<p>D&#8217;autres ateliers devraient ouvrir sur le premier trimestre 2013, et vous en verrez un aperçu dans notre <a href="http://www.js-attitude.fr/tout-sur-les-ateliers/">catalogue</a>.  En attendant, nous vous invitons à regarder le détail des pages des ateliers pour découvrir les programmes détaillées, le lieu de formation, les tarifs et dates, etc.</p>

<h2>Nouveau planning, nouvel endroit&nbsp;!</h2>

<p>Historiquement, les sessions Attitude inter-entreprises se sont toujours tenues le samedi, presque exclusivement dans les locaux de Clever Age Paris, boulevard des Capucines, à deux pas d&#8217;Opera.  Nous tenons d&#8217;ailleurs à les remercier encore une fois chaleureusement pour ce <em>gentleman&#8217;s agreement</em> qui aura duré plus de 2 ans et sans lequel les formations Attitude n&#8217;auraient peut-être pas connu le succès qui est le leur aujourd&#8217;hui.</p>

<p>Toutefois, cette contrainte de planning (samedi seulement, une journée maximum) posait problème à de nombreux stagiaires potentiels, et limitait la gamme des ateliers proposables.</p>

<p>La dernière session du samedi, chez Clever Age, se tiendra le 27/10 pour un <a href="http://www.js-attitude.fr/js-guru/">JS Guru</a>.  Après cela, <strong>toutes les sessions seront en semaine dans notre nouveau lieu</strong>.  Jusqu&#8217;à nouvel ordre, elles se tiendront entre le mardi et le vendredi.</p>

<p>La barre latérale du site (ou sur mobile, le bas de page) listent à tout moment l&#8217;ensemble des dates prévues, avec le cas échéant un indicateur de places restantes (s&#8217;il en reste 4 ou moins).  À ce jour, les dates suivantes sont proposées&nbsp;:</p>

<ol>
<li><a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> samedi 27/10</li>
<li><del><a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> jeudi 22/11</del> <em>session retirée avant inscriptions en raison d&#8217;un fort volume d&#8217;intra</em></li>
<li><del><a href="http://www.js-attitude.fr/js-guru/">JS Guru</a> jeudi 29/11</del> <em>session retirée avant inscriptions en raison d&#8217;un fort volume d&#8217;intra</em></li>
<li><a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> vendredi 07/12</li>
<li><a href="http://www.js-attitude.fr/js-total/">JS Total</a> du mardi 11 au vendredi 14/12</li>
<li><a href="http://www.js-attitude.fr/coffee-script/">CoffeeScript</a> mardi 18/12</li>
<li><a href="http://www.js-attitude.fr/coffee-guru/">Coffee Guru</a> du mercredi 19 au vendredi 21/12</li>
</ol>


<p>Aucune session n&#8217;est prévue sur la dernière semaine de décembre&nbsp;; passez donc les fêtes avec proches, que diable&nbsp;!</p>

<p>Par ailleurs, à compter du 20/11/2012, nous serons également beaucoup plus disponibles pour des formations intra-entreprises et/ou sur-mesure.  Là aussi, la <em>sidebar</em> et une page dédiée vous informent et vous permettent de <a href="http://www.js-attitude.fr/demander-une-intra-ou-custom/">nous contacter sur ce sujet</a>.</p>

<p>Parlons à présent du nouvel endroit dans lequel auront lieu les formations Attitude.</p>

<p>Nous avons longuement cherché un endroit qui corresponde à nos exigences et à l&#8217;esprit des formations&nbsp;: décontracté, agréable et professionnel.  Nous avons donc été emballés en découvrant et visitant l&#8217;espace La Rochefoucauld du Groupe Formeret.</p>

<p>Le Groupe Formeret ne fait qu&#8217;une chose et le fait manifestement très bien&nbsp;: héberger des formations, séminaires, examens, etc.  Leurs 4 lieux sont impeccables, parfaitement accessibles à tous, conviviaux et lumineux.  À leur rencontre, on sent tout de suite leur volonté de bien faire et de fournir un service d&#8217;excellente qualité.  Nous espérons avoir trouvé en eux un partenaire de confiance sur la durée.</p>

<p>Nous avons choisi en priorité l’espace La Rochefoucauld en raison de sa situation géographique (Notre-Dame de Lorette / Saint-Georges, presque aussi central qu’Opéra) mais aussi du cachet du lieu (très calme, entouré de verdure, avec une vue imprenable sur le Sacré-Cœur) et de sa taille, qui permet d’éviter un effet «&nbsp;grands bureaux&nbsp;».</p>

<p>La formation se déroule dans une salle privative <strong>climatisée, lumineuse, fonctionnelle et très confortable</strong>.  L’ensemble des locaux sont facilement accessibles en transports en commun et classés ERP, notamment accessibles aux Personnes à Mobilité Réduite.</p>

<p><em>Espace La Rochefoucauld<br/>
11 rue de La Rochefoucauld<br/>
75009 Paris</em></p>

<p><img class="center" src="http://www.js-attitude.fr/images/espace-la-rochefoucauld.jpg" width="789" height="127" title="Quelques vues de l’Espace La Rochefoucauld" ></p>

<p>Situé en plein cœur de Paris, tout près de la Gare Saint-Lazare et d&#8217;Opera, il est accessible <em>via</em> pas moins de 6 lignes de métro, 2 lignes de RER et 7 lignes de bus&nbsp;:</p>

<ul>
<li>Métro&nbsp;: Saint-Georges, Trinité (ligne 12), St-Lazare (lignes 3, 9, 12, 13 et 14), Chaussée d&#8217;Antin (lignes 7 et 9)</li>
<li>RER&nbsp;: Haussman Saint-Lazare (ligne E), Auber (ligne A)</li>
<li>Bus&nbsp;: Saint-Georges (67, 74), La Bruyere (74), Trinité (26, 32, 43, 68, 81)</li>
</ul>


<p>On trouve également nombre de parkings alentour.</p>

<iframe width="789" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.fr/maps/ms?msa=0&amp;msid=217317377156117787165.0004c7b86726d25e19cd6&amp;ie=UTF8&amp;t=m&amp;ll=48.878102,2.334294&amp;spn=0.00247,0.008465&amp;z=17&amp;output=embed"></iframe>


<br /><small>Afficher <a href="https://maps.google.fr/maps/ms?msa=0&amp;msid=217317377156117787165.0004c7b86726d25e19cd6&amp;ie=UTF8&amp;t=m&amp;ll=48.878102,2.334294&amp;spn=0.00247,0.008465&amp;z=17&amp;source=embed" style="color:#0000FF;text-align:left">Espace la Rochefoucauld</a> sur une carte plus grande</small>


<p>Chaque stagiaire <strong>amène son propre poste de travail ou ordinateur portable</strong>.</p>

<p>L’accès internet est assuré par une connexion fibre très haut débit.  La salle fournit un accès Wi-Fi ainsi que des connexions RJ45 pour les postes qui le nécessiteraient.</p>

<div id="housing">
  <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="94.42px" height="100px" viewBox="0 0 94.42 100" enable-background="new 0 0 94.42 100" xml:space="preserve">
  <path d="M20.15,63.002c4.859-0.011,8.808-3.96,8.831-8.831c-0.023-4.875-3.972-8.824-8.831-8.832
    c-4.885,0.008-8.834,3.958-8.828,8.832C11.315,59.042,15.265,62.991,20.15,63.002L20.15,63.002z"/>
  <path d="M20.15,54.171"/>
  <path d="M29.576,56.229v7.639H16.034c-6.551,0.046-6.56,8.458,0,8.448h17.768c2.598,0.01,4.224-2.083,4.225-4.439V56.229
    C38.025,49.864,29.587,49.864,29.576,56.229L29.576,56.229z"/>
  <path d="M47.019,22.104"/>
  <path d="M47.019,22.104"/>
  <path d="M39.166,51.679H74.43c5.194-0.012,8.242,3.319,8.234,7.801v12.731H39.166V51.679L39.166,51.679z"/>
  <path d="M9.641,44.312c-0.01-6.947-9.648-6.947-9.641,0V100h9.858V85.645h74.973v14.247h9.589V56.88
    c0.025-7.328-9.719-7.328-9.696,0v17.171H9.641V44.312L9.641,44.312z"/>
  <path d="M47.019,0c-12.06,0.014-21.853,9.906-21.83,22.104c-0.023,12.204,9.77,22.092,21.83,22.101
    c12.098-0.009,21.894-9.897,21.886-22.101C68.912,9.906,59.116,0.014,47.019,0z M47.019,39.113
    c-9.276-0.008-16.81-7.618-16.792-17.009C30.209,12.718,37.743,5.109,47.019,5.09c9.314,0.019,16.85,7.628,16.848,17.014
    C63.868,31.495,56.333,39.105,47.019,39.113z"/>
  <path d="M44.744,29.901h4.93v-3.845c0.028-1.034,0.51-2.015,1.786-2.87c1.318-0.845,4.934-2.568,4.932-7.096
    c0.002-4.54-3.795-7.656-6.988-8.343c-3.193-0.635-6.653-0.2-9.099,2.491c-2.208,2.407-2.671,4.313-2.655,8.504h4.927v-0.975
    c-0.018-2.233,0.24-4.597,3.468-5.254c1.718-0.34,3.355,0.205,4.333,1.135c1.105,1.106,1.115,3.554-0.65,4.769l-2.763,1.897
    c-1.639,1.036-2.193,2.191-2.221,3.899V29.901L44.744,29.901z"/>
  <polygon points="44.744,36.891 44.744,31.854 49.728,31.854 49.728,36.891 44.744,36.891 "/>
  <path d="M47.236,34.399"/>
  </svg>

  <p>Vous n’êtes pas en région parisienne et cherchez un hébergement ?  Nous vous proposons de <a href="http://www.accorhotels.com/fr/booking/map-search.shtml?xml=world&xsl=cm&Lang=Fr&startCountry=FR&siteOrigine=ALL&Search=Adr&searchtext=11+rue+de+La+Rochefoucauld+75009+Paris" target="_blank">consulter les hôtels Accor à proximité</a> (Ibis, Mercure, Novotel, etc.) ou pourquoi pas de passer par <a href="https://www.airbnb.fr/s/11-Rue-de-la-Rochefoucauld--75009-Paris--France" target="_blank">airbnb</a> ?</p>
</div>


<h2>Plus d&#8217;articles didactiques</h2>

<p>Jusqu&#8217;à présent, le manque de temps ne nous a pas permis de donner au site JS Attitude l&#8217;envergure pédagogique et didactique que nous souhaitions.  Des dizaines de sujets d&#8217;articles et de didacticiels attendent depuis de nombreux mois d&#8217;être rédigés et publiés.  Les articles du site et la <em>timeline</em> Twitter se résumaient pour l&#8217;essentiel à des annonces d&#8217;atelier et du marketing.</p>

<p>Si le marketing ne disparaîtra pas tout-à-coup du flux (pour le moment, Twitter et le bouche-à-oreille restent nos seuls canaux de communication et de marketing), les articles d&#8217;annonce, eux, n&#8217;auront plus cours&nbsp;: les pages détaillées des ateliers existent et contiendront toujours la liste des prochaines dates&nbsp;; leurs URLs ne changeront pas.  Et la <em>sidebar</em> du site reprend ces informations.</p>

<p>En revanche, nous allons prendre de plus en plus de temps pour produire et publier des articles, didacticiels et suggestions de veille technologique, sur un rythme régulier et, nous l&#8217;espérons, assez fréquent.  Nous espérons qu&#8217;ainsi, vous trouverez le site toujours plus intéressant et utile.</p>

<h2>Bientôt une nouvelle plate-forme intégrée</h2>

<p>Il n&#8217;est plus possible pour le moment de vous inscrire directement en ligne, en payant par carte bancaire ou PayPal.  Nous travaillons à l&#8217;aboutissement d&#8217;un projet interne de plate-forme qui va regrouper l&#8217;ensemble des services en ligne dont les formations Attitude ont besoin&nbsp;: présentation, suivi des places disponibles, inscription ou demande de convention en ligne, attestations de présence, factures, évaluations par les stagiaires, accès aux ressources pédagogiques et forums de discussion entre les stagiaires passés et les formateurs, etc.</p>

<p>Les sites dédiés (<code>js-attitude.fr</code>, <code>git-attitude.fr</code>, etc.) se concentreront alors sur les contenus didactiques, et recroiseront diverses infos (dont le planning des sessions) avec la plate-forme.</p>

<p>En attendant, vous pouvez naturellement toujours nous faire une <a href="http://www.js-attitude.fr/demander-une-convention/">demande de convention</a> <em>via</em> le formulaire habituel.</p>

<h2>En résumé…</h2>

<p>Dès mi-novembre, Attitude passe la 5ème&nbsp;!  Nous espérons vous retrouver nombreux à nos sessions, et que le travail et la passion intenses que nous mettons dans la conception et la tenue de nos ateliers sauront vous séduire.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Un nouveau site JS Attitude]]></title>
    <link href="http://www.js-attitude.fr/2012/08/26/un-nouveau-site-js-attitude/"/>
    <updated>2012-08-26T18:30:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/08/26/un-nouveau-site-js-attitude</id>
    <content type="html"><![CDATA[<p>Après bientôt <strong>2 ans</strong> d&#8217;existence, JS Attitude change de look et reprend son rôle principal, qui n&#8217;est juste de promouvoir les sessions de formation, mais aussi de <strong>transmettre</strong> et de <strong>partager</strong>.</p>

<!-- more -->


<p>Parce que nous anticipons des articles de plus en plus <strong>riche en codes sources</strong>, parce que nous souhaitons <strong>enrichir la discussion</strong> autour des commentaires et des réseaux sociaux, et parce que nous trouvons le look par défaut beaucoup plus propre que ce qu&#8217;on sur le site en place, nous avons passé JS Attitude sur <a href="http://www.octopress.org/">Octopress</a>.</p>

<p>Vous trouverez déjà un nouvel article, plutôt long, de nature didactique (une catégorie que nous avons bien l&#8217;intention d&#8217;enrichir régulièrement désormais)&nbsp;: <a href="http://www.js-attitude.fr/enfin-maitriser-les-expressions-rationnelles/">Enfin maîtriser les expressions rationnelles</a>.  Ce sujet, qui nous tient à cœur, n&#8217;avait pas pour autant sa place dans <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a>, aussi il figure désormais sur le site, libérant de la place dans l&#8217;atelier pour approfondir d&#8217;autres sujets plus importants (par exemple la programmation fonctionnelle et les prototypes).</p>

<p>Le <strong>catalogue 2012–2013</strong>, lui aussi, est à l&#8217;honneur, au travers de la nouvelle page <a href="http://www.js-attitude.fr/tout-sur-les-ateliers/">Tout sur les ateliers</a> et des pages détaillées pour nos formations existantes (mais parfois remaniées) et nouvelles (pas moins de 3 d&#8217;ici fin 2012&nbsp;!).  Un article d&#8217;annonce spécifique est dans les fourneaux.</p>

<p>Vous trouverez d&#8217;ailleurs une liste à jour des <strong>dates planifiées</strong> des ateliers JS Attitude dans la barre latérale (ou inférieure, sur des affichages étroits), ainsi qu&#8217;en bas de chaque page atelier du catalogue.  À partir de la mi-novembre 2012, vous aurez jusqu&#8217;à 8 jours de formation proposés par mois&nbsp;!</p>

<p>Nous espérons que le nouveau JS Attitude vous plaira.  Comme toujours, n&#8217;hésitez pas à échanger avec nous <em>via</em> les commentaires en bas de chaque page.  À très vite pour des articles et formations du tonnerre&nbsp;!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enfin maîtriser les expressions rationnelles]]></title>
    <link href="http://www.js-attitude.fr/2012/08/13/enfin-maitriser-les-expressions-rationnelles/"/>
    <updated>2012-08-13T22:37:00+02:00</updated>
    <id>http://www.js-attitude.fr/2012/08/13/enfin-maitriser-les-expressions-rationnelles</id>
    <content type="html"><![CDATA[<p>Une couverture exhaustive des expressions rationnelles a jusqu’ici fait partie de l&#8217;atelier <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a>.  Elle occupait bien 1h, voire 1h30, en matinée.</p>

<p>C&#8217;est un sujet qui me tient véritablement à cœur, pour les raisons que je vais développer dans les deux premiers titres.  Mais on m&#8217;a quelquefois fait remonter, très justement, qu’une telle couverture, au sein d&#8217;un atelier de 8h, est tout-à-fait hors de proportion, et que le temps libéré pourrait être utilement mis à profit en entrant plus dans le détail d&#8217;autres aspects (programmation fonctionnelle, structuration de code…).</p>

<p>Afin de ne pas simplement cesser de transmettre ces connaissances et de «&nbsp;convertir&nbsp;» les gens au bon usage des expressions rationnelles, j’ai donc opté pour l’approche inverse&nbsp;: sortir ce contenu des formations pour en faire un contenu librement accessible sur le site de JS Attitude&nbsp;!</p>

<p>Qui sait&nbsp;?  Peut-être cet article, s’il est suffisamment bien fichu, deviendra-t-il, à son petit niveau, une sorte de référence francophone sur ce sujet, comme le sont désormais des articles de <a href="http://www.git-attitude.fr/">Git Attitude</a> sur les <a href="http://www.html5rocks.com/en/tutorials/casestudies/technitone/">clés SSH</a> ou <a href="http://www.git-attitude.fr/2010/07/18/heberger-un-serveur-git-avec-gitosis-linux-osx/">l&#8217;installation de Gitosis</a>…</p>

<!-- more -->


<h2>Le croque-mitaine</h2>

<p>Traditionnellement, les expressions rationnelles ne sont pas enseignées.  Il est déjà assez difficile de trouver un prof de BTS ou DUT capable de faire véritablement du Java, sans même parler de Python, Ruby ou JavaScript, pour espérer avoir carrément des cours décents d&#8217;expressions rationnelles.</p>

<p>Popularisées par Perl, les expressions rationnelles débarquent en général au travers d&#8217;un morceau de code parfaitement abscons, comme le dégorgement inattendu d&#8217;un fragment de fichier binaire au beau milieu du code source.  Et de fait, quel développeur, pas forcément junior mais globalement sain d&#8217;esprit, n’aurait pas le cœur au bord des lèvres en tombant tout à coup sur ce genre de chose&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\w+\[([\w-]+)(?:[*~^$]?=([&#39;&quot;])?(.+?)\1\]/</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>


<p>C’est vrai, quoi, comprenez-les.  Les pauvres, personne ne les a prévenus, sinon ils n’auraient pas choisi le pâté de tripes à midi, vous pensez bien, c’était trop risqué.</p>

<p>Faute d&#8217;enseignement, faute de rationalité justement, faute de démystification utile, les expressions rationnelles restent à la périphérie de nos regards et de notre conscience, les <em>banshees</em> du développement, on les garde soigneusement à distance de peur qu&#8217;en y touchant elles ne nous attrapent tout entiers et nous volent ce qui nous reste de raison, tels de petits Cthulhus tout de symboles vêtus.</p>

<h2>Le bon outil pour manipuler du texte</h2>

<p>Naturellement, il n&#8217;en est rien, ne prêtez pas attention à cette porte qui claque quelque part dans l&#8217;asile d&#8217;Arkham.  Les regex restent un outil extrêmement efficace pour extraire rapidement des éléments spécifiques d&#8217;un contenu textuel.  Par exemple, repérer certaines balises dans du HTML&nbsp;; trouver les lettres en double dans un texte&nbsp;; capitaliser un texte (mettre ses initiales en majuscules et le reste en minuscules)&nbsp;; détecter qu’un texte est bien une adresse e-mail (ou IP, ou URL…) valide&nbsp;; etc.</p>

<p>Il est bien sûr possible d&#8217;écrire des algorithmes manuels pour tous ces usages, mais ceux-ci présentent deux inconvénients majeurs vis-à-vis des expressions rationnelles équivalentes&nbsp;:</p>

<ul>
<li>Ils sont souvent largement plus verbeux (jusqu&#8217;à plusieurs centaines de lignes de code), et donc sujets à potentiellement bien davantage de bugs, notamment des erreurs de bornes (les erreurs +1/-1, ou <em>fencepost errors</em>) et de conditions de boucle.</li>
<li>Ils sont en général significativement plus lents que leur équivalent à base d’expressions rationnelles.</li>
</ul>


<p>Vous me rétorquerez peut-être qu&#8217;ils sont bien plus lisibles.  C&#8217;est un argument aussi classique que fallacieux.</p>

<p>À part les cas triviaux d&#8217;analyse de texte (par exemple, en compter les consonnes), ce n&#8217;est pas vrai&nbsp;: tout traitement un tant soit peu avancé requiert automatiquement un volume non négligeable de code, avec ses variables, conditions, etc.  La lisibilité se dégrade rapidement, ou à défaut, on obtient du code lisible, mais volumineux, dont il faut en outre comprendre l&#8217;algorithme pour en saisir l’objectif.  Même si on se cantonne aux cas où le code alternatif est court, l&#8217;expression rationnelle équivalente est, elle, triviale, et ne devrait donc pas poser de souci de lisibilité.</p>

<p>Qui plus est, la lisibilité d&#8217;une expression rationnelle est perçue traditionnellement comme mauvaise pour deux raisons&nbsp;: d&#8217;une part, nombre de gens écrivent des expressions balourdes, pataudes, ne tirant pas le meilleur parti de la syntaxe qu&#8217;elles alourdissent inutilement. D‘autre part, cette syntaxe, bien que grammaticalement assez simple, est effectivement assez peu intuitive&nbsp;: la majorité des développeurs ont donc connu le syndrome du «&nbsp;WTF?!&nbsp;» lors de leurs premières rencontre avec de telles expressions, ce qui entraîne un préjugé.</p>

<p>Enfin, nombre de personnes n&#8217;utilisent pas (où n&#8217;ont pas à disposition, comme c’est hélas le cas en JavaScript natif) le drapeau de syntaxe <code>x</code>, qui permet de découper et commenter une expression rationnelle lors de sa déclaration, ce qui accomplit des miracles en termes de lisibilité.  Nous y reviendrons en fin d’article avec la bibliothèque XRegExp.</p>

<h2>Un mot de vocabulaire</h2>

<h3>Expression rationnelle ou régulière&nbsp;?</h3>

<p>La terminologie anglaise ne connaît que <em>regular expression</em>, l&#8217;adjectif insistant sur le fait que, comme pour l&#8217;algèbre relationnelle, les expressions régulières sont basées sur des principes mathématiques déterministes et que la syntaxe est donc sans ambiguïté (si si&nbsp;!).  En France, sans doute à la faveur de traductions initiales ayant pris quelques libertés, on s&#8217;est vite retrouvé avec les deux locutions <em>expression régulière</em> et <em>expression rationnelle</em>.  On rencontre l’une à peu près aussi souvent que l’autre.  J’ai personnellement pris le parti de la seconde, car je trouve que le <em>rationnelle</em> met davantage en avant ce principe de conception&nbsp;; employez l’un ou l’autre comme bon vous semble, mais soyez juste cohérent avec vous-même&nbsp;!</p>

<p>Dans les deux cas, c&#8217;est tout de même assez long, aussi utilise-t-on la majeure partie du temps l’abréviation <em>regex</em>, en anglais comme en français, qui a en outre le mérite d’éviter le débat précédent.  Dans le reste de cet article, j’emploierai cette abréviation dans un souci de concision.</p>

<h3>«&nbsp;Reguex&nbsp;» ou «&nbsp;Redjex&nbsp;»&nbsp;?</h3>

<p>C’est la question suivante, posée par ceux qui se soucient de leur prononciation (et je les en félicite).  Bien que l’origine du <em>reg</em> (<em>regular</em>) incite à l’utilisation d’un g dur («&nbsp;reguex&nbsp;»), la prononciation anglaise usuelle ne s’intéresse qu’à l’abréviation elle-même, et comme le g est doux devant les e et les i, on prononce effectivement «&nbsp;redjex&nbsp;».</p>

<h2>Les exemples classiques</h2>

<p>Afin d’essayer de bien illustrer tout l’intérêt que peut représenter l’emploi des regex dans son code, en voici quelques-unes assez classiques.  Le lecteur qui pinaille trouvera naturellement tout un tas de contre-exemples, mais le but n&#8217;est pas ici de recenser les solutions en béton armé, qui doivent gérer une telle pléthore de cas qu’elles sont en effet complexes (bien moins que les algorithmes associés, néanmoins).  Il s’agit de montrer des cas pas trop ahurissants&nbsp;!  On n&#8217;aura par ailleurs recours qu&#8217;aux syntaxes gérées nativement par JavaScript (pas de groupes nommés, notamment).</p>

<ul>
<li><code>[0-9a-f]+</code> — Nombre entier hexadécimal</li>
<li><code>(['"]).*?\1</code> — Chaîne de caractères (guillemets simples ou doubles, mais cohérents entre eux&nbsp;; pas d’échappement)</li>
<li><code>[\w.-]+@[\w-]+\.\w{3,6}</code> — E-mail (basique)</li>
<li><code>[\w-]+(\.[\w-]+){1,}</code> — FQDN (nom de domaine, hors IRI)</li>
<li><code>&lt;[^&gt;]+&gt;</code> — Balise XML (ouvrante ou fermante)</li>
<li><code>\&amp;(lt|gt|apos|quot|amp);</code> — Échappement XML (les cinq entités obligatoires)</li>
<li><code>(?:\d{1,3}\.){3}\d{1,3}</code> — IP (basique)</li>
<li><code>(?:(?:1?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:1?\d{1,2}|2[0-4]\d|25[0-5])</code> — IP (exact&nbsp;: contrôle des valeurs)</li>
<li><code>[a-z]+://[^:/]+(?::\d+)?(?:/[^?]+)?(?:\?[^#]+)?(?:#.+)?</code> — URL (syntaxes des composants un peu laxistes…)</li>
</ul>


<h2>Déconstruire une expression rationnelle</h2>

<p>Devant le foutoir (ben si, des fois, le foutoir&nbsp;!) que peut représenter une regex au premier abord, l’important est de savoir la déconstruire.  Et là, c&#8217;est un peu comme les poupées russes&nbsp;: on procède de l&#8217;extérieur vers l&#8217;intérieur.  La clé est aussi de savoir bien repérer les classes, groupes et leurs éventuelles imbrications, pour délimiter ainsi notre analyse.</p>

<p>Par exemple, prenons la première, <code>[0-9a-f]+</code>.  On y repère une classe, c&#8217;est-à-dire une série de possibilités pour un unique caractère&nbsp;: <code>[0-9a-f]</code>, qui est assez facile à décoder&nbsp;: de 0 à 9 et de a à f, donc un caractère hexadécimal. Et le quantificateur <code>+</code> vient indiquer qu&#8217;on s&#8217;attend à trouver ça au moins une fois.</p>

<p>Plus compliqué&nbsp;: <code>(?:\d{1,3}\.){3}\d{1,3}</code>.  Là, on doit repérer tout de suite le groupe (non capturant en l&#8217;occurrence, mais passons) <code>(?:\d{1,3}\.)</code>, et noter qu’il est quantifié 3 fois.  On va même remarquer rapidement que la suite de l&#8217;expression est en fait une redite du contenu du groupe, au point final près.  Les regex n’ont hélas pas de syntaxe pour dire &#8220;schéma X, N fois, séparé par schéma Y&#8221;&nbsp;: on se retrouve le plus souvent à dire &#8220;X + Y, N fois, puis X une dernière fois&#8221;.  Sans pouvoir nommer les groupes, ça fait du doublon, comme ici.  Et le contenu répété, <code>\d{1,3}</code>, est assez simple&nbsp;: «&nbsp;un chiffre décimal, 1 à 3 fois&nbsp;».</p>

<p>Et ainsi de suite, en découpant le problème originel de plus en plus, pour se concentrer sur des fragments assez petits pour être analysés directement sans péter un câble.  Mais croyez-moi, avec un peu de pratique, c&#8217;est <em>beaucoup</em> plus facile qu&#8217;il n&#8217;y paraît.</p>

<h2>Construire une expression rationnelle</h2>

<p>Pour construire une regex, on fait l&#8217;inverse&nbsp;: on part des petits composants, et on… compose, au fur et à mesure.  Plus on a bien découpé à la base, plus la construction se fera naturellement, et moins on aura de répétition.</p>

<p>Supposons par exemple que vous souhaitiez créer une expression de validation d&#8217;un login, qui aurait les contraintes suivantes&nbsp;: uniquement des caractères alphanumériques ASCII, à raison d&#8217;un minimum de 6 et d&#8217;un maximum de 12.  Comment s&#8217;y prend-on&nbsp;?</p>

<p>Déjà, tous les caractères ont la même contrainte, ce qui est bon signe&nbsp;: ça va nous éviter de multiplier les composants.  On doit donc d&#8217;abord exprimer la contrainte sur <em>un</em> caractère, sous forme d&#8217;une série de valeurs possibles.  C&#8217;est là le rôle des classes, on écrit donc <code>[a-z0-9]</code> pour lister les caractères et chiffres ASCII.  Il ne nous reste plus qu&#8217;à quantifier ça, entre 6 et 12 occurrences&nbsp;: <code>[a-z0-9]{6,12}</code>.</p>

<h2>Apprivoiser les expressions rationnelles pas à pas</h2>

<p>La syntaxe des expressions rationnelles a finalement assez peu d’éléments potentiels.  Et ce d&#8217;autant plus que JavaScript ne gère pas nativement certaines extensions intéressantes, comme le drapeau <code>x</code> ou les groupes nommés.  Nous allons examiner ces possibilités tranquillement, une par une, dans la suite de cet article.</p>

<h3>Syntaxe des regex litérales en JavaScript</h3>

<p>En JavaScript, vous avez deux manières d&#8217;obtenir une regex utilisable&nbsp;: en l&#8217;écrivant directement dans le code, de façon statique, sous forme d&#8217;un litéral.  Ou en utilisant une construction d&#8217;objet explicite, avec la syntaxe <code>new RegExp</code>.</p>

<p>Dans la pratique, cette deuxième syntaxe n&#8217;a d&#8217;intérêt que si vous devez construire une regex dynamiquement sur la base de contenus que vous ne connaissez pas encore en écrivant le code (par exemple, une saisie utilisateur).  Dans tous les autres cas, préférez la syntaxe litérale, plus concise.</p>

<p>Une regex litérale en JavaScript, c&#8217;est trois choses&nbsp;: les délimiteurs, l&#8217;expression elle-même, et les drapeaux de contrôle.</p>

<h4>Délimiteurs</h4>

<p>En JavaScript, on n&#8217;a pas le choix&nbsp;: une regex litérale est forcément encadrée par des <em>slashes</em> (<code>/</code>).  Du coup, tout slash dans l&#8217;expression devra être échappé (<code>\/</code>), ce qui peut vite donner des trucs cocasses (<code>/^https?:\/\//</code>)…</p>

<h4>Drapeaux (<em>flags</em>)</h4>

<p>Les drapeaux de contrôle se placent après le slash de terminaison.  JavaScript en reconnaît trois&nbsp;:</p>

<ul>
<li><code>i</code> est très pratique et fréquent&nbsp;: <em>Insensible à la casse</em>.  Permet d&#8217;éviter la galère de devoir spécifier tous nos caractères possibles en minuscules ET en majuscules, lorsqu&#8217;on accepte les deux…</li>
<li><code>g</code> rend la regex <em>Globale</em>&nbsp;: au lieu de se concentrer sur la première correspondance du texte, elle pourra agir sur toutes les correspondances.  Change fondamentalement les comportements de recherche et de remplacement…</li>
<li><code>m</code> est souvent mal compris.  Lui qui signifie <code>Multi-lignes</code> ne veut pas dire que notre regex va automatiquement marcher sur des correspondances à plusieurs lignes (et tout particulièrement, il ne permet pas au caractère générique total, <code>.</code>, de sauter les lignes), juste que les ancres (indications de position) <code>^</code> et <code>$</code> correspondront aux bords de ligne, et non aux bords du texte total.  Ce drapeau sert plus rarement.</li>
</ul>


<p>Ainsi par exemple, une regex de nombre hexadécimal sera plus probablement <code>/[0-9a-f]/i</code>, car dans la plupart des langages, la casse des lettres est sans importance pour les litéraux numériques.</p>

<h3>Représenter un seul caractère de correspondance</h3>

<p>Armés de ces connaissances de base sur la structure extérieure d&#8217;une regex, voyons l&#8217;intérieur.  Une regex, fondamentalement, sert à chercher une correspondance dans un texte (voire à vérifier la correspondance du texte dans son ensemble).  L&#8217;unité de base de ce travail, c&#8217;est le caractère.  Quelles contraintes peut-on donc exprimer sur un seul caractère, pierre angulaire de la suite&nbsp;?</p>

<h4>Caractères litéraux (non spéciaux)</h4>

<p>Tout d&#8217;abord, on peut exiger qu&#8217;il s&#8217;agisse d&#8217;un caractère précis.  Lui et pas un autre.  Il suffit alors d&#8217;utiliser le caractère directement, comme un litéral.  Par exemple, <code>a</code> ne peut correspondre qu&#8217;au caractère A minuscule latin (code numérique 97).</p>

<p>Si votre caractère joue un rôle spécial dans les regex, il faudra l&#8217;échapper (sauf si vous êtes au sein d&#8217;une classe, ce qui la plupart du temps vous en dispense automatiquement, sympa).  Par exemple, /?[a-z]=/i ne va pas faire correspondre un texte avec un point d&#8217;interrogation suivi d&#8217;une lettre ASCII suivi du signe égale&nbsp;: le point d&#8217;interrogation est un quantificateur, comme on le verra plus loin, et s&#8217;attend donc même à avoir un contenu qui le précède&nbsp;: cette regex est invalide et votre interpréteur JS considérera ce morceau de code comme invalide.  Il faudra employer <code>/\?[a-z]=/i</code> pour obtenir le résultat souhaité.</p>

<h4>Classes explicites</h4>

<p>Si on se contentait de comparer des caractères précis, on n&#8217;aurait pas besoin des regex&nbsp;: une bête comparaison de chaîne suffirait&nbsp;!</p>

<p>Afin d’exprimer une <em>série de possibilités</em> pour un caractère unique dans le texte analysé, on utilise des <em>classes</em>.  Elles consistent à lister les caractères possibles, entre deux crochets.  Par exemple, pour représenter les voyelles minuscules latines&nbsp;:</p>

<pre><code>[aeiouy]
</code></pre>

<p>Évidemment, si on doit se farcir <em>toutes</em> les possibilités manuellement, ça va vite faire longuet…  Lorsque les caractères possibles sont adjacents dans la table de caractères, on peut donc juste séparer les limites de la plage voulue par un tiret&nbsp;:</p>

<pre><code>[a-z]
</code></pre>

<p>Et on peut naturellement combiner caractères explicites et plages, comme ci-dessous pour les chiffres hexadécimaux par exemple&nbsp;:</p>

<pre><code>[a-f0-9]
</code></pre>

<p>Il peut par ailleurs arriver qu&#8217;on souhaite exprimer non pas tous les caractères autorisés mais plutôt, par concision, <em>tous les caractères interdits</em>.  On parle alors de <em>classe négative</em>, qui doit commencer par un circonflexe.  Ainsi, pour interdire les chiffres arabes par exemple, mais autoriser tout le reste, on dirait ceci&nbsp;:</p>

<pre><code>[^0-9]
</code></pre>

<p>Le sens spécial qu’ont le crochet fermant, le tiret et le circonflexe à l&#8217;intérieur d&#8217;une définition de classe obligent soit à les échapper (en les précédant d&#8217;un <em>backslash</em>), soit, pour le tiret, à le placer en bord de classe, afin de lever l&#8217;ambiguïté (s&#8217;il n&#8217;a pas de caractère des deux côtés, il n&#8217;indique pas un intervalle).</p>

<h4>Classes prédéfinies</h4>

<p>Certaines séries sont suffisamment communes pour disposer de syntaxes raccourcies.  Celles-ci se présentent sous forme d&#8217;un <em>backslash</em> suivi d&#8217;une lettre.  Les trois lettre gérées par JavaScript sont&nbsp;:</p>

<ul>
<li><code>d</code> pour <em>digit</em>, qui regroupe les chiffres arabes.</li>
<li><code>w</code> pour <em>word</em>, qui regroupe les lettres latines ASCII, les chiffres arabes et le tiret de soulignement (<em>underscore</em>)</li>
<li><code>s</code> pour <em>space</em>, qui regroupe les espacements usuels ASCII (espace, tabulations, saut de ligne, saut de page)</li>
</ul>


<p>Si la lettre est minuscule, on a une classe positive (seuls ces caractères-là).  Si elle est majuscule, on a une classe négative (tout sauf ces caractères-là).  Ainsi, <code>\d</code> équivaut à <code>[0-9]</code> et <code>\W</code> équivaut à <code>[^a-z0-9_]</code>.</p>

<h4>ASCII vs. Unicode</h4>

<p>Il est dommage que JavaScript ne gère pas mieux les jeux de caractères «&nbsp;réels&nbsp;», ceux employés par les langues.  Ainsi, <code>\w</code> ignore les signes diacritiques (accents, cédilles, etc.) et d&#8217;une manière générale toutes les lettres non latines (grecques, allemandes, asiatiques…). Dans le même esprit, <code>\s</code> ignore l&#8217;espace insécable, aussi fréquente soit-elle.</p>

<p>Nous verrons en fin d&#8217;article qu&#8217;une petite bibliothèque JavaScript, XRegExp, étend considérablement les possibilités des regex en JavaScript, si vous avez ce type de besoin.</p>

<h4>Combinaisons de classes</h4>

<p>Il est possible de combiner des classes prédéfinies au sein d&#8217;une classe explicite, éventuellement avec d&#8217;autres caractères spécifiques, par exemple comme ceci&nbsp;:</p>

<pre><code>[\wéèêëàâäîïôöûüç\s\u00a0]
</code></pre>

<p>On trouve ici les alphanumériques latin/arabe, le soulignement, les principales lettres françaises à signe diacritique, les espacements ASCII et l&#8217;espace insécable.  JavaScript nous autorise en effet à utiliser la syntaxe de code litéral Unicode <code>\uxxxx</code>.  On a ici le code 160 (<code>a0</code> en hexadécimal), qui est l&#8217;espace insécable dans la table Unicode.  C&#8217;est une syntaxe qu&#8217;on retrouve également dans CSS.</p>

<h4>La classe générique&nbsp;: point</h4>

<p>Une classe particulière est le <em>Any char</em>&nbsp;: <code>.</code> (point).  Elle représente en théorie n&#8217;importe quel caractère.  Dans la pratique, elle est limitée par l&#8217;activation (ou pas) d&#8217;un flag de comportement indiquant si elle comprend aussi les sauts de ligne ou non.  Un tel flag n&#8217;existe pas dans les regex JavaScript standard, et le point ne correspond jamais à un saut de ligne, même avec le mode multi-ligne (contrairement à d&#8217;autres moteurs de regex, comme par exemple celui de Ruby).  Là encore, XRegExp offre une amélioration.</p>

<p>En tous les cas, il faut faire attention au risque d&#8217;employer un point litéral sans réfléchir, car le point des regex voudra dire «&nbsp;n&#8217;importe quel caractère&nbsp;»&nbsp;!  Pensez alors à l&#8217;échapper avec un <em>backslash</em>.</p>

<h3>Représenter plusieurs caractères successifs</h3>

<p>Jusqu&#8217;à présent, nous nous sommes concentrés sur l&#8217;établissement d&#8217;un critère pour <em>un</em> caractère.  Mais dans une analyse de texte, c&#8217;est une séquence de caractères que nous allons examiner&nbsp;!</p>

<h4>Parties fixes</h4>

<p>Le plus simple consiste à utiliser, à la suite, les descriptifs de motif pour chaque caractère du texte à analyser.  Par exemple, si vous voulez juste une lettre suivie d&#8217;un chiffre, vous direz sans doute&nbsp;:</p>

<pre><code>[a-z]\d
</code></pre>

<p>Toutefois, la plupart du temps vous souhaitez aussi indiquer qu&#8217;un motif donné est acceptable pour davantage qu&#8217;un seul caractère&nbsp;: peut-être 2, 10, au moins 20, maximum 15, un ou plus, ou un nombre quelconque (y compris aucun)…  C&#8217;est le rôle des <em>quantificateurs</em>.</p>

<h4>Quantificateurs</h4>

<p>Un quantificateur est une syntaxe spéciale qui, employée derrière un élément de la regex, modifie sa quantité potentielle.  À la base, tout composant de la regex est attendu exactement une fois.  On peut toutefois le faire suivre des syntaxes de quantification que voici&nbsp;:</p>

<ul>
<li><code>?</code> signifie «&nbsp;zéro ou un&nbsp;», ce qui revient à dire «&nbsp;optionnel&nbsp;».</li>
<li><code>+</code> signifie «&nbsp;au moins un&nbsp;».</li>
<li><code>*</code> signifie «&nbsp;un nombre quelconque de fois&nbsp;» (y compris zéro).</li>
</ul>


<p>Il est aussi possible d’utiliser des bornes précises, au moyen d’une syntaxe un peu plus longue, encadrée par des accolades (<em>curly braces</em>)&nbsp;:</p>

<ul>
<li><code>{4}</code> pour «&nbsp;exactement 4 fois&nbsp;».</li>
<li><code>{4,12}</code> pour «&nbsp;entre 4 et 12 fois&nbsp;».</li>
<li><code>{4,}</code> pour «&nbsp;au moins 4 fois&nbsp;».</li>
</ul>


<p>La syntaxe <code>{,4}</code> n&#8217;existe pas, pour la simple raison qu&#8217;on obtient le même résultat avec <code>{0,4}</code>.</p>

<h4>Quantificateurs réticents</h4>

<p>Les quantificateurs vus à l&#8217;instant sont tous qualifiés de <em>gourmand</em> (<em>greedy quantifiers</em>), au sens où ils tenteront systématiquement d’obtenir <em>la plus grande correspondance possible</em>.  Ce n’est pas toujours ce qu’on veut.  Prenons par exemple le texte analysé suivant&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;p&gt;&lt;a</span> <span class="na">href=</span><span class="s">&quot;#deuze&quot;</span><span class="nt">&gt;</span>Et yop la deuze<span class="nt">&lt;/a&gt;</span> - <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;#quarte&quot;</span><span class="nt">&gt;</span>Et yop la quarte<span class="nt">&lt;/a&gt;&lt;/p&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Imaginons maintenant que nous voulons récupérer les liens.  Une regex naïve serait <code>/&lt;a.*&gt;.+&lt;\/a&gt;/g</code>. Mais ça va nous donner un unique résultat&nbsp;: <code>"&lt;a href="#deuze"&gt;Et yop la deuze&lt;/a&gt; - &lt;a href="#quarte"&gt;Et yop la quarte&lt;/a&gt;"</code>.  Ah.  Flûte.  Le souci ici vient du fait qu’on utilise des quantificateurs gourmands.  On pourrait bien sûr remplacer le premier par <code>[^&gt;]*</code> histoire d’être sûrs de s&#8217;arrêter en fin de balise ouvrante, mais ça ne marche pas pour le deuxième, car si on faisait <code>…&gt;[^&lt;]+&lt;/a&gt;</code>, on s&#8217;arrêterait dès qu’un lien contient des balises…</p>

<p>On peut plutôt recourir à des versions réticentes.</p>

<p>Il suffit de rajouter un <code>?</code> à la fin du quantificateur gourmand usuel&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="sr">/&lt;a.*?&gt;.+?&lt;\/a&gt;/g</span>
</span></code></pre></td></tr></table></div></figure>


<p>Et là, on obtient bien deux résultats, un par lien.  Les quantificateurs vont s’arrêter au <em>premier chevron fermant rencontré</em> et au <em>premier <code>&lt;/a&gt;</code> rencontré</em>.</p>

<h3>Alternative entre deux séquences</h3>

<p>Pour indiquer une alternative entre caractères, on utilise généralement une classe.  Par exemple, <code>[arz]</code> signifie «&nbsp;a, ou r, ou z&nbsp;».  Mais comment faire pour des séquences&nbsp;?  On les sépare par un <em>pipe</em> (<code>|</code>).</p>

<p>Ainsi, <code>hello|world</code> signifie «&nbsp;hello ou world&nbsp;».  Et <code>[1-9][0-9]*|0x[0-9a-f]+</code> signifie «&nbsp;un litéral nombre décimal (chiffre de 1 à 9 suivi éventuellement de chiffres décimaux) ou un litéral nombre hexadécimal (0 puis x puis un nombre quelconque non nul de chiffres hexadécimaux)&nbsp;».</p>

<p>Attention cependant, il peut y avoir un piège quant à la portée de l&#8217;alternative&nbsp;: par défaut, elle s’applique à <em>tout ce qui l&#8217;entoure</em>&nbsp;!  C’est vite un souci, mais nous allons voir comment le résoudre dans un instant.</p>

<h3>Groupes</h3>

<p>Il est possible de rassembler des fragments de vos regex en groupes.  Il y a plusieurs raisons de faire cela&nbsp;: pour quantifier plus qu’un simple caractère (mais carrément toute une séquence), pour limiter une alternative, ou pour obtenir comme résultat, en plus de la correspondance globale, des segments précis de celle-ci.</p>

<p>La syntaxe fondamentale des groupes est toujours la même&nbsp;: on entoure un groupe par des parenthèses&nbsp;: <code>(</code> et <code>)</code>.</p>

<h4>Grouper pour quantifier une séquence de caractères</h4>

<p>Imaginons que vous souhaitiez faire une regex toute bête&nbsp;: «&nbsp;au moins deux mots&nbsp;».  Au sens «&nbsp;au moins deux séries de non-espacements&nbsp;», par exemple.  La séquence «&nbsp;série de non-espacements&nbsp;» est assez facile&nbsp;: <code>\S+</code> (majuscule). Et les mots seraient séparés par, justement, des séries d&#8217;espacements&nbsp;: <code>\s+</code> (minuscule).</p>

<p>Pour dire «&nbsp;deux mots&nbsp;», on pourrait donc faire <code>\S+\s+\S+</code>.  Hmmmm.  Mais pour dire «&nbsp;au moins deux mots&nbsp;»&nbsp;?  On fait comment.  Comme souvent lorsqu&#8217;il s&#8217;agit de séquences alternées (motifs X séparés par motif Y), on doit la représenter en deux parties&nbsp;:</p>

<ol>
<li>Motif X</li>
<li>Motif Y puis Motif X, le tout un certain nombre de fois (le tout quantifié, quoi).</li>
</ol>


<p>Ici, vu qu&#8217;on veut «&nbsp;au moins 2 mots&nbsp;», le quantificateur de cette deuxième partie serait «&nbsp;au moins 1 fois&nbsp;», donc le <code>+</code>.  Mais on ne peut pas juste faire <code>\S+\s+\S++</code>, ça n&#8217;aurait aucun sens.  Comment faire que ce dernier <code>+</code> sache à quoi il s’applique, en l’occurrence <code>\s+\S+</code>&nbsp;?  Avec les groupes, pardi&nbsp;:</p>

<pre><code>\S+(\s+\S+)+
</code></pre>

<p>Le groupe constitue une seule entité grammaticale, donc le quantificateur qui le suit s&#8217;applique au groupe dans son entier.</p>

<h4>Grouper pour limiter une alternative</h4>

<p>Un autre emploi fréquent du groupe est pour limiter une alternative (une utilisation de <code>|</code>, le <em>pipe</em>).  Par défaut, on l&#8217;a vu, une alternative s&#8217;applique à tout ce qui l&#8217;entoure.  Mais si elle figure au sein d&#8217;un groupe, elle se limite à ce groupe.</p>

<p>Supposons que vous vouliez autoriser les textes «&nbsp;hello world&nbsp;», «&nbsp;hallo world&nbsp;» et «&nbsp;hi world&nbsp;». Le «&nbsp;world&nbsp;» étant commun on peut limiter l&#8217;alternative au premier mot.  Mais si on fait ceci :</p>

<pre><code>hello|hallo|hi world
</code></pre>

<p>…on se plante, car ça correspondrait à «&nbsp;hello&nbsp;», «&nbsp;hallo&nbsp;» ou «&nbsp;hi world&nbsp;», ce qui n&#8217;est pas ce qu&#8217;on veut.  Il faut délimiter l&#8217;alternative avec un groupe&nbsp;:</p>

<pre><code>(hello|hallo|hi) world
</code></pre>

<p>Et voilà, le tour est joué&nbsp;!</p>

<h4>Grouper pour récupérer individuellement des fragments précis de la correspondance</h4>

<p>Le dernier usage des groupes, qui est extrêmement utile, est la possibilité de référencer des portions spécifiques de la correspondance obtenue.  Par exemple, vous essayez de repérer, au sein d’un texte, une chaîne française de date, au format <code>jj/mm/aaaa</code>.  Non seulement vous voulez vérifier que la chaîne est bonne, mais aussi en extraire les composants.  Au lieu de «&nbsp;juste&nbsp;» écrire ceci :</p>

<pre><code>\d{2}/\d{2}/\d{4}
</code></pre>

<p>…vous pourriez isoler chaque composant dans son groupe&nbsp;:</p>

<pre><code>(\d{2})/(\d{2})/(\d{4})
</code></pre>

<p>Vous allez alors obtenir, en plus de la correspondance globale (par exemple «&nbsp;25/07/2012&nbsp;») des groupes 1 à 3 («&nbsp;25&nbsp;», «&nbsp;07&nbsp;» et «&nbsp;2012&nbsp;»).</p>

<p>Les groupes sont numérotés de 1 à 9.  Au-delà, vous ne disposez plus de numéros.  Vous ne pouvez donc avoir recours «&nbsp;que&nbsp;» à 9 groupes numérotés dans une expression.  On parle de <em>groupes capturants</em>.</p>

<h4>Numérotation et imbrication de groupes</h4>

<p>Il est naturellement possible d&#8217;imbriquer les groupes.  Par exemple, comme ceci&nbsp;:</p>

<pre><code>(\d{4}-(\d{2})-(\d{2}))
</code></pre>

<p>Mais alors, quel groupe a quel numéro, et quelle valeur&nbsp;?  La règle de numérotation est simple&nbsp;: <em>dans l&#8217;ordre des parenthèses ouvrantes</em>.  Ainsi, sur le texte <code>2012-07-28</code>, on obtiendrait&nbsp;:</p>

<ul>
<li>Le groupe 1&nbsp;: <code>2012-07-28</code></li>
<li>Le groupe 2&nbsp;: <code>07</code></li>
<li>Et le groupe 3&nbsp;: <code>28</code></li>
</ul>


<h4><em>Backreferences</em> («&nbsp;<em>backrefs</em>&nbsp;»)</h4>

<p>Dès l&#8217;instant où un groupe est numéroté, il devient possible de le référencer, tant pour un remplacement que pour une recherche.</p>

<p>Le cas de figure du remplacement est assez classique et utilise la syntaxe <code>$numéro</code>.  Supposons que vous ayez à transformer des dates américaine (mois/jour/année) en dates techniques (année-mois-jour).  On pourrait procéder ainsi&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">usDate</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(\d{2})\/(\d{2})\/(\d{4})/</span><span class="p">,</span> <span class="s1">&#39;$3-$2-$1&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Là où ça devient vraiment pratique, c’est au sein même du motif de recherche.  On s&#8217;en sert couramment pour faire correspondre des délimiteurs.  Supposons que vous vouliez définir un motif qui autorise de part et d&#8217;autre l&#8217;apostrophe (<code>'</code>) ou le guillemet (<code>"</code>), mais qui exige que les deux extrêmités correspondent.  La version pourrie, ce serait&nbsp;:</p>

<pre><code>'.+?'|".+?"
</code></pre>

<p>Et encore, elle pose plein de soucis.  Mais vous pouvez facilement simplifier ça (surtout si ce qu&#8217;il y a entre les apostrophes/guillemets est un motif compliqué) en évitant toute répétition.  Pour le cas où l&#8217;apostrophe/guillemet initial constituerait le premier groupe numéroté du motif&nbsp;:</p>

<pre><code>(['"]).+?\1
</code></pre>

<p>Pratique, non&nbsp;? Le <code>\1</code> fait référence au texte qui <em>a correspondu au groupe 1</em>&nbsp;: il faut alors que dans le texte analysé, on trouvé à l&#8217;endroit du <code>\1</code> <em>extactement le même texte que pour le groupe 1</em>.</p>

<h4>Groupes non capturants</h4>

<p>Neuf groupes, c&#8217;est beaucoup et vous n&#8217;aurez normalement pas besoin de tous.  En revanche, il arrive souvent que vous ne <em>souhaitiez pas exploiter le groupe individuellement</em>, et n&#8217;ayez donc pas besoin de lui attribuer un numéro.  Par exemple, vous l&#8217;auriez utilisé uniquement pour une des autres raisons&nbsp;: quantifier une séquence ou limiter une alternative.  Il est alors dommage de «&nbsp;polluer&nbsp;» les groupes numérotés légitimes avec ceux-là, vous obligeant à examiner les groupes 2, 6 et 9 au lieu de 1, 2 et 3.  Comment faire&nbsp;?</p>

<p>C’est tout simple, il suffit de recourir alors à des <em>groupes non capturants</em>.  Par défaut, un groupe est <em>capturant</em>&nbsp;: il s’octroie un numéro.  Mais lorsque vous l’utilisez juste à des fins structurelles, vous pouvez le rendre non capturant en préfixant son contenu par <code>?:</code>.  Ça donnerait quelque chose comme ça&nbsp;:</p>

<pre><code>([A-Z]{2})(?:\.\d+)+([A-Z])
</code></pre>

<p>Dans l&#8217;exemple ci-dessous, on a d&#8217;abord un groupe capturant, qui comprend deux lettres latines majuscules&nbsp;: <code>([A-Z]{2})</code>.  C’est le groupe numéro 1.  Puis on a un groupe non capturant, dont le seul objectif est de pouvoir ensuite appliquer à son contenu le quantificateur <code>+</code>&nbsp;: <code>(?:\.\d+)</code>, à savoir un point suivi d&#8217;au moins un chiffre.  Et finalement, on a un deuxième groupe capturant, qui aura donc le numéro 2&nbsp;: <code>([A-Z])</code>, soit une lettre latine majuscule.</p>

<p>En utilisant judicieusement la syntaxe non capturante, vous n&#8217;utilisez des numéros que pour les groupes que vous souhaitez effectivement référencer ensuite.  En plus, un groupe capturant est souvent plus lourd à gérer par les moteurs de regex qu&#8217;un groupe non capturant&nbsp;: vous améliorez donc aussi, même si ce n’est pas toujours sensible, la performance de votre regex.</p>

<h3>Indiquer la position avec les ancres</h3>

<p>Jusqu’ici, nous avons rédigé des regex qui, dans la pratique, pouvaient correspondre à un texte figurant n’importe où dans la chaîne de caractères examinée.</p>

<p>Par exemple, la regex <code>h[ea]ll?o</code> correspondra bien sûr à <code>hallo</code>, <code>hello</code> et <code>halo</code>, mais aussi à <code>hello world</code>, <code>say hello, mark!</code> et surtout à <code>chaloupe</code> ou <code>halogène</code>.</p>

<p>Il arrive fréquemment qu’on ait besoin de préciser une contrainte de positionnement sur tout ou partie d’une regex.  C’est le rôle des <em>ancres</em>.</p>

<p>Les regex JavaScript reconnaissent les ancres suivantes&nbsp;:</p>

<ul>
<li><code>^</code> (circonflexe, en anglais <em>caret</em>).  Il s&#8217;agit du début de la chaîne de caractère examinée.  Si la regex utilise le drapeau multi-lignes (<code>m</code>), il peut en fait s’agir de n&#8217;importe quel début de ligne (début de texte ou juste après un saut de ligne, <code>\n</code>).</li>
<li><code>$</code> (dollar).  C’est la fin de la chaîne, ou en mode multi-ligne ce peut aussi être une fin de ligne.</li>
<li><code>\b</code> est le <em>word Boundary</em>.  C’est une ancre extrêmement utile, qui désigne une <em>bordure de mot</em>.  Ça inclut notamment les sauts de lignes, espaces, la ponctuation et les extrêmités du texte.  Par symétrie, on a aussi <code>\B</code> (majuscule), qui comme pour les classes est le contraire de <code>\b</code>&nbsp;: elle indique qu&#8217;on ne se <em>situe pas</em> à la bordure d&#8217;un mot.</li>
</ul>


<p>Quelques exemples&nbsp;:</p>

<pre><code>^halo  // correspond à "halo" et "halogène" et "halo éclatant", mais pas à "chaloupe" ou "un halo."
halo$  // correspond à "halo", mais ni "halogène", ni "halo éclatant", ni "chaloupe", ni "un halo."
\bhalo // correspond à "halo", "un halo.", "halo éclatant" et "halogène", mais pas "chaloupe"
halo\b // correspond à "halo", "un halo." et "halo éclatant", mais ni "halogène" ni "chaloupe"
</code></pre>

<p>Ainsi, pour indiquer qu&#8217;une regex correspond à <em>l&#8217;ensemble d&#8217;un texte</em>, on l&#8217;encadre par <code>^</code> et <code>$</code>, comme ceci&nbsp;:</p>

<pre><code>^h[ea]llo w(?:orld|elt)$ // "hello world", "hallo welt", "hello welt", "hallo world" et c'est tout.
</code></pre>

<h3>Conditions sur la suite du texte (<em>lookaheads</em>)</h3>

<p>Parfois, une contrainte sur position ne suffit pas.  Il faut carrément indiquer une condition sur <em>la suite du texte</em>.</p>

<h4>Lookaheads positifs</h4>

<p>Peut-être quelque chose comme &#8220;un chiffre, à condition qu&#8217;il soit suivi par deux autres chiffres&#8221;.  Mais on ne veut pas pour autant accumuler les deux chiffres qui suivent dans la correspondance.  On utilise pour cela un <em>positive lookahead</em>, identifié comme un groupe avec un préfixe <code>?=</code> &nbsp;:</p>

<pre><code>\d(?=\d\d) // "2" dans "237" ou "243", mais pas dans "24M", "2", "2TZ" ou "2T4".
</code></pre>

<h4>Lookaheads négatifs</h4>

<p>Il est évidemment possible aussi d’exprimer une contrainte <em>négative</em> sur la suite du texte&nbsp;: ce qu&#8217;on ne <em>veut pas</em> trouver après.  Au lieu de <code>?=</code>, on utilise alors <code>?!</code>.  Pour prendre l&#8217;inverse de l&#8217;exemple précédent, on pourrait dire &#8220;un chiffre, pourvu qu&#8217;il ne soit pas suivi par un autre chiffre&#8221;&nbsp;:</p>

<pre><code>\d(?!\d) // "2" dans "2", "2TZ" ou "2T4", mais pas dans "237", "243" ou "24M".
</code></pre>

<p>Tout ça peut sembler un peu basique, mais voici un bel exemple combiné et imbriqué, et une fois que vous l&#8217;avez digéré, vous êtes au point sur les lookaheads&nbsp;!  Examinez plutôt&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">numberString</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(\d)(?=(\d\d\d)+(?!\d))/g</span><span class="p">,</span> <span class="s2">&quot;$1 &quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Oh pétard&nbsp;!  Ça fait quoi, ça&nbsp;?!?</p>

<p>Eh bien «&nbsp;tout simplement&nbsp;», ça ajoute les espaces en séparateurs de milliers entre les groupes de 3 chiffres (en partant de la droite, évidemment).  En somme, grâce aux lookaheads, on arrive à analyser <em>par la droite</em> alors que les regex travaillent <em>par la gauche</em>.</p>

<p>Voilà de quoi vous faire tourner les méninges…  Petite astuce pour décrypter cette regex&nbsp;: on cherche en fait à remplacer chaque <em>fin de groupe numérique</em> (hors le dernier) par son dernier chiffre suivi du séparateur.  Et comment sait-on qu&#8217;on a des groupes numériques valables derrière soi&nbsp;?  Parce qu&#8217;on a <em>un nombre de chiffres multiple de 3</em> derrière soi.  Voilà, je vous laisse décortiquer tout ça…  Quelques exemples de conversion&nbsp;:</p>

<pre><code>'243'         // '243'
'2431'        // '2 431'
'24315'       // '24 315'
'243157'      // '243 157'
'2431576'     // '2 431 576'
…
</code></pre>

<h4>Lookbehinds&nbsp;?</h4>

<p>Dans certains cas de figure, il peut être également utile de poser une contrainte sur <em>le texte d&#8217;avant</em>, indépendamment de comment on a éventuellement traversé ce texte dans un début de correspondance.  On aurait alors recours aux <em>lookbehinds</em>, qui traditionnellement s&#8217;écrivent <code>?&lt;=</code> et <code>?&lt;!</code>.  Cependant, JavaScript ne propose pas, en standard, cette syntaxe.</p>

<p>Et pour le coup, XRegExp ne permet pas de simuler cette possibilité.  Il existe toutefois la possibilité de <a href="http://blog.stevenlevithan.com/archives/javascript-regex-lookbehind">les simuler si besoin</a>.</p>

<h2>Les API JavaScript qui utilisent les regex</h2>

<p>JavaScript nous permet de recourir aux regex au moyen de diverses API, certaines très connues, d&#8217;autres moins.</p>

<h3>String#match et String#replace</h3>

<p>Certainement les deux plus connues.  On utilise la première pour chercher des correspondances, l&#8217;autre pour les remplacer.</p>

<p>Selon que la regex utilise le flag <code>g</code> ou non, on cherche (ou remplace) toutes les correspondances, ou seulement la première&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="s1">&#39;hello world!&#39;</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\w+/g</span><span class="p">)</span> <span class="c1">// =&gt; [&#39;hello&#39;, &#39;world&#39;]</span>
</span><span class='line'><span class="s1">&#39;hello world!&#39;</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\w+/</span><span class="p">)</span>  <span class="c1">// =&gt; [&#39;hello&#39;]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ce que beaucoup ne savent pas, c&#8217;est que le résultat n&#8217;est pas juste un tableau, avec sa propriété <code>length</code> et les index numériques (0, 1, etc.).  En tout cas, quand le drapeau <code>g</code> est absent.  Il est alors aussi doté de propriétés spéciales&nbsp;: <code>index</code>, qui indique la position de la première correspondance, et <code>input</code>, qui reprend le texte complet analysé.  Voyez plutôt&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="s1">&#39;hello world!&#39;</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\s(\w+)/</span><span class="p">)</span>
</span><span class='line'><span class="nx">result</span><span class="p">.</span><span class="nx">length</span> <span class="c1">// =&gt; 2</span>
</span><span class='line'><span class="nx">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>     <span class="c1">// =&gt; &#39; world&#39; (la correspondance complète)</span>
</span><span class='line'><span class="nx">result</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>     <span class="c1">// =&gt; &#39;world&#39; (le groupe numéroté 1)</span>
</span><span class='line'><span class="nx">result</span><span class="p">.</span><span class="nx">index</span>  <span class="c1">// =&gt; 5 (la position, en partant de 0, de la correspondance complète dans le texte)</span>
</span><span class='line'><span class="nx">result</span><span class="p">.</span><span class="nx">input</span>  <span class="c1">// =&gt; &#39;hello world!&#39; (le texte analysé)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Quant à <code>replace</code>, elle accepte en fait deux formats pour son deuxième argument (qui décrit le remplacement).</p>

<p>Le premier format est une chaîne de caractères&nbsp;: c&#8217;est le motif de remplacement.  On peut alors y trouver les syntaxes spéciales&nbsp;:</p>

<pre><code>$&amp; (la correspondance complète)
$` (le texte avant la correspondance)
$' (le texte après)
$1 à $9 (les groupes numérotés).
</code></pre>

<p>Par exemple&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="s1">&#39;hello world!&#39;</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\w+/g</span><span class="p">,</span> <span class="s1">&#39;[$&amp;]&#39;</span><span class="p">)</span>   <span class="c1">// =&gt; &#39;[hello] [world]!&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>On peut aussi, et c&#8217;est là que ça devient balèze, utiliser une fonction, qui prend alors comme arguments la correspondance totale, les groupes numérotés, l&#8217;index de début de correspondance et au final le texte analysé d&#8217;origine.  La fonction renvoie le texte qui remplacera la correspondance globale.  Voyez plutôt&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="s1">&#39;HELLO WORLD!&#39;</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\b(\w)(\w*)/g</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">word</span><span class="p">,</span> <span class="nx">initial</span><span class="p">,</span> <span class="nx">remainder</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">initial</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="o">+</span> <span class="nx">remainder</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">();</span>
</span><span class='line'><span class="p">})</span>
</span><span class='line'><span class="c1">// =&gt; &#39;Hello World!&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<h3>String#split</h3>

<p>La plupart des développeurs connaissent <code>split</code>, par exemple comme ci-dessous&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="s1">&#39;hello world this is nice&#39;</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span>  <span class="c1">// =&gt; [&#39;hello&#39;, &#39;world&#39;, &#39;this&#39;, &#39;is&#39;, &#39;nice&#39;]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Mais beaucoup ne savent pas, et c&#8217;est dommage, que le séparateur peut être une regex.  Ainsi, imaginez le texte suivant&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="s1">&#39;01-17.32  28--17/41&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Pour extraire les groupes numériques, avec un séparateur textuel, on est dans la mouise.  Mais avec une regex, aucun souci&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="s1">&#39;01-17.32  28--17/41&#39;</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="sr">/\D+/</span><span class="p">)</span>  <span class="c1">// =&gt; [&#39;01&#39;, &#39;17&#39;, &#39;32&#39;, &#39;28&#39;, &#39;17&#39;, &#39;41&#39;]</span>
</span></code></pre></td></tr></table></div></figure>


<h3>String#search</h3>

<p>Pour information, il existe aussi une API <code>search</code> qui vous renvoie uniquement la position de la correspondance (-1 si introuvable), et non tout le détail que renvoie <code>match</code>.  Du coup, si c&#8217;est la seule info qui vous intéresse (la position), c&#8217;est plus performant.</p>

<h3>RegExp</h3>

<p>Les regex JavaScript sont toutes des objets (comme presque toujours en JavaScript), en l&#8217;occurrence des instances de <code>RegExp</code>.  Elles ont notamment deux méthodes&nbsp;: <code>exec</code> et <code>test</code>.</p>

<p>Voici deux expressions rigoureusements équivalentes&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="sr">/\w+/</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="s1">&#39;hello world!&#39;</span><span class="p">)</span> <span class="c1">// &lt;=&gt; &#39;hello world!&#39;.match(/\w+/)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Le drapeau <code>g</code> est sans effet sur <code>exec</code>, en revanche.  On tape toujours dans la première correspondance.  Le résultat renvoyé est strictement identique à celui décrit pour <code>match</code>, avec les propriétés numériques ainsi que <code>index</code> et <code>input</code>.</p>

<p>Si tout ce qui vous intéresse, c&#8217;est qu&#8217;il y ait ou non correspondance, vous pouvez vous contenter de <code>test</code>, qui renvoie un simple booléen et s&#8217;exécute donc plus rapidement (un peu comme tout à l&#8217;heure, avec la différence entre <code>match</code> et <code>search</code>).</p>

<p>Il est donc possible de créer dynamiquement une regex, avec <code>new RegExp(motif, drapeaux)</code>.  Le seul intérêt, naturellement, par rapport à un litéral, c&#8217;est si le contenu du motif (ou des drapeaux) varie avec le temps, par exemple suite à une saisie utilisateur.</p>

<p>Supposons que vous autorisiez l&#8217;internaute à taper des lettres qui servent de filtre de recherche, ce qu&#8217;on appelle une <em>fuzzy search</em>&nbsp;: ça correspondrait à tout texte où ces lettres existent dans l&#8217;ordre, peu importe ce qu&#8217;il y aurait entre elles.</p>

<p>Par exemple, pour la saisie <code>jel</code>, vous voudriez rechercher tout texte contenant un <code>j</code>, plus loin un <code>e</code> et encore plus loin un <code>l</code>.  En somme, la regex serait <code>j.*e.*l</code>.  Supposons que la saisie soit effectuée dans un champ dont l&#8217;attribut <code>id</code> vaudrait <code>filter</code>&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">expr</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;filter&#39;</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>      <span class="c1">// $(&#39;#filter&#39;).val() avec jQuery…</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">regex</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;.*&#39;</span><span class="p">),</span> <span class="s1">&#39;g&#39;</span><span class="p">);</span>  <span class="c1">// Peu importe la casse…</span>
</span></code></pre></td></tr></table></div></figure>


<p>En réalité, pour que cet exemple soit vraiment blindé, il faudrait d&#8217;abord &#8220;échapper&#8221; les caractères spéciaux saisis (spéciaux au sens des regex), en les préfixant par un <em>backslash</em> (<code>\</code>), mais vous saisissez l&#8217;idée.</p>

<p>C&#8217;est bien là la seule raison de recourir à <code>new RegExp</code> (ainsi peut-être qu&#8217;un motif bourré de <em>slashes</em> (<code>/</code>)).  Le reste du temps, un litéral est plus concis et plus performant.</p>

<h2>Mise en application</h2>

<p>Afin de vous permettre de vous faire la dent, voici quelques exercices pour pratiquer.</p>

<h3>Exo 1</h3>

<p>Prenez le premier paragraphe de <a href="http://fr.lipsum.com/feed/html">ce lorem ipsum</a> et collez-le dans une <code>String</code>.  Extrayez-en les mots de plus de 4 lettres non suivis d&#8217;une espace.</p>

<p><a href="http://jsbin.com/anowaq/1/edit?console">Voir la solution sur JSBin</a></p>

<h3>Exo 2</h3>

<p>Parmi les <a href="http://www.acronymfinder.com/Index-AC.html">acronymes connus commençant par AC</a>, sortez tout ceux comportant une répétition consécutive de lettres, quelles qu’elles soient.</p>

<p><a href="http://jsbin.com/onulix/1/edit?console">Voir la solution sur JSBin</a></p>

<h3>Exo 3</h3>

<p>Examinez le HTML résultat de <a href="http://www.google.com/search?q=formation+js&amp;hl=fr">cette recherche Google</a> et sortez les titres, URLs et positions (au sein des résultats naturels uniquement) des pages JS Attitude.</p>

<p><a href="http://jsbin.com/abolur/3/edit?html,javascript,console">Voir la solution sur JSBin</a></p>

<h2>Étendre les regex JavaScript&nbsp;: XRegExp</h2>

<p>Bien que le moteur de regex de JavaScript ne soit pas mauvais (et plutôt rapide), à l&#8217;usage, on regrette rapidement l&#8217;absence de certaines fonctionnalités présentes dans des moteurs plus récents comme ceux qu&#8217;on peut trouver dans les versions actuelles de Perl, Python ou Ruby, pour ne citer qu&#8217;eux.</p>

<p>Heureusement, grâce au boulot acharné de Steve Levithan, fan de regex et de JavaScript, il existe un palliatif de premier choix&nbsp;: l&#8217;excellente bibliothèque <a href="http://xregexp.com/">XRegExp</a>.</p>

<p>Celle-ci nous offre de nouvelles syntaxes, de nouveaux drapeaux de traitement, et va même jusqu&#8217;à corriger quelques bugs exotiques des moteurs de regex proposés par les principaux navigateurs.</p>

<h3>Comment exploiter XRegExp&nbsp;?</h3>

<p>XRegExp n&#8217;est pas natif à JavaScript, aussi les litéraux de type <code>/…/</code> ne peuvent pas s&#8217;en servir automatiquement.  Il faut recourir à la fonction <code>XRegExp</code>, qui a les mêmes arguments que le constructeur <code>new RegExp</code>&nbsp;: le motif et les drapeaux.  Par exemple&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">regex</span> <span class="o">=</span> <span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;&lt;p class=&quot;result&quot;&gt;.+?&lt;/p&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;is&#39;</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Cette syntaxe a un léger inconvénient (évidemment)&nbsp;: puisqu&#8217;on est dans un litéral chaîne de caractères et non un litéral regex, il va falloir doubler tous les <em>backslashes</em>.  Ainsi, <code>/\w+\s</code> donnera <code>XRegExp('\\w+\\s')</code>.</p>

<p>Là où les instances de <code>RegExp</code> et <code>String</code> ont des méthodes directes, <code>XRegExp</code> a choisi d&#8217;avoir une API 100% «&nbsp;statique&nbsp;», appelable dans l&#8217;espace de nom <code>XRegExp</code>.  Ce ne sont pas des méthodes sur les objets retournés par <code>XRegExp(…)</code>. On trouve donc une méthode <code>XRegExp.exec</code> et une méthode <code>XRegExp.test</code>, mais il y a aussi les équivalents des méthodes complémentaires disponibles sur <code>String</code> : <code>split</code> et <code>replace</code>.  Par ailleurs, l’API de <code>XRegExp</code> fournit de nombreuses méthodes utilitaires, comme <code>forEach</code> pour itérer facilement sur les correspondances, <code>escape</code> et <code>build</code> pour construire dynamiquement une regex depuis des fragments divers, et j&#8217;en passe. <a href="http://xregexp.com/api/">Jetez un œil à l’API complète</a>.</p>

<h3>Groupes capturants nommés</h3>

<p><code>XRegExp</code> nous fournit de nombreuses améliorations syntaxiques.  Celle qui est de loin ma préférée consiste à permettre de nommer les captures.  Ainsi, plutôt que d&#8217;avoir un bête numéro de 1 à 9, on a un nom explicite.  Par exemple, au lieu de ceci&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="sr">/(\w+)\s+\1/</span>
</span></code></pre></td></tr></table></div></figure>


<p>…on peut préférer ceci (certes plus long, mais plus explicite)&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="err">&#39;</span><span class="p">(</span><span class="o">?&lt;</span><span class="nx">word</span><span class="o">&gt;</span><span class="err">\\</span><span class="nx">w</span><span class="o">+</span><span class="p">)</span><span class="err">\</span><span class="nx">s</span><span class="o">+</span><span class="err">\\</span><span class="nx">k</span><span class="o">&lt;</span><span class="nx">word</span><span class="o">&gt;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Nous verrons des exemples plus «&nbsp;percutants&nbsp;» tout à l&#8217;heure, en combinant cette possibilité avec la syntaxe étendue.</p>

<p>Un groupe nommé est forcément capturant (il se voit donc aussi affecter un numéro, comme une capture usuelle), et démarre par le préfixe <code>?&lt;nom&gt;</code>.  Une <em>backref</em> nommée, au lieu d&#8217;être <em>backslash</em> + numéro, est <code>\k&lt;nom&gt;</code>.</p>

<p>Ce qui est vraiment sympa, c&#8217;est que cette prise en charge va jusqu’au bout&nbsp;:</p>

<ul>
<li>Dans les textes de remplacement utilisés comme deuxième argument de <code>replace</code>&nbsp;: on a droit à la syntaxe <code>${nom}</code>.</li>
<li>Dans les propriétés de l&#8217;objet résultat renvoyé par <code>match</code> et transmis aux fonctions de remplacement&nbsp;: en plus des propriétés numériques usuelles, on a des propriétés nommées comme le groupe.</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">regex</span> <span class="o">=</span> <span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;(?&lt;word&gt;\\w+)\s+\\k&lt;word&gt;&#39;</span><span class="p">);</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">text</span> <span class="o">=</span> <span class="s1">&#39;Franchement XRegExp XRegExp ça déboite !&#39;</span><span class="p">;</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">XRegExp</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span> <span class="nx">regex</span><span class="p">);</span>
</span><span class='line'><span class="nx">result</span><span class="p">.</span><span class="nx">word</span> <span class="c1">// =&gt; &#39;XRegExp&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>XRegExp</code> fournit encore d&#8217;autres possibilités, telles que les commentaires monoligne intégrés ou les commutateurs de mode à la volée, mais je leur trouve peu d&#8217;intérêt.  Vous pouvez en savoir plus sur la page des <a href="http://xregexp.com/syntax/">syntaxes proposées par XRegExp</a>.</p>

<h3>Nouveaux drapeaux</h3>

<p><code>XRegExp</code> introduit par ailleurs trois nouveaux drapeaux qui altèrent le fonctionnement standard du moteur.  En plus des drapeaux usuels (<code>i</code>, <code>m</code> et <code>g</code>), on trouve désormais&nbsp;:</p>

<ul>
<li><code>s</code> pour <em>Singleline</em>.  Ce mode est également connu sous le nom «&nbsp;dotall&nbsp;», et signifie que le caractère générique <code>.</code> (point) peut correspondre à véritablement n&#8217;importe quoi, <em>y compris des sauts de ligne</em> (4 caractères Unicode possibles, dont <code>\n</code> et <code>\r</code>).  Extrêmement pratique quand on traite du HTML et qu&#8217;on veut extraire des balises de contenu…</li>
<li><code>n</code> est le drapeau de <em>capture explicite</em>.  Avec lui, seules les groupes nommés sont capturants&nbsp;: les groupes non nommés n&#8217;ont plus besoin d&#8217;être préfixés par <code>?:</code> pour être non capturants.</li>
<li><p><code>x</code> est le <em>eXtended mode</em>, votre nouveau meilleur ami.  Il permet d&#8217;utiliser un <em>espacement libre</em> et aussi des <em>commentaires de fin de ligne</em>.  Prenons l&#8217;exemple d&#8217;une analyse de date au format A-M-J&nbsp;:</p>

<p>  (\d{4})-(\d{2})-(\d{2})</p></li>
</ul>


<p>Pas horrible, mais pas top non plus.  On pourrait faire&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;(\\d{4}) # Year \</span>
</span><span class='line'><span class="s1">         - \</span>
</span><span class='line'><span class="s1">         (\\d{2}) # Month \</span>
</span><span class='line'><span class="s1">         - \</span>
</span><span class='line'><span class="s1">         (\\d{2}) # Day&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Déjà plus lisible, non&nbsp;?  Grâce à la possibilité d&#8217;ignorer les espacements non qualifiés, tout espacement litéral est considéré comme ignorable dans le motif.  À vous d&#8217;utiliser une autre syntaxe (le générique <code>\s</code> ou une entité numérique spécifique) en cas de besoin.</p>

<p>On peut remplacer (ou augmenter) ces commentaires assez simples en nommant les captures&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;(?&lt;year&gt;\\d{4}) - (?&lt;month&gt;\\d{2}) - (?&lt;day&gt;\\d{2})&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Du coup, l&#8217;objet résultat n&#8217;aurait pas seulement des propriétés 1, 2 et 3, mais aussi et surtout <code>year</code>, <code>month</code> et <code>day</code>.</p>

<p>Et maintenant une décomposition d&#8217;URL pas trop tatillonne&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">regex</span> <span class="o">=</span> <span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;^(?&lt;scheme&gt; [^:/?]+ ) ://   # aka protocol   \n\</span>
</span><span class='line'><span class="s1">                  (?&lt;host&gt;   [^/?]+  )       # domain name/IP \n\</span>
</span><span class='line'><span class="s1">                  (?&lt;path&gt;   [^?]*   ) \\??  # optional path  \n\</span>
</span><span class='line'><span class="s1">                  (?&lt;query&gt;  .*      )       # optional query&#39;</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">);</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">text</span> <span class="o">=</span> <span class="s1">&#39;http://google.com/path/to/file?q=1&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">parts</span> <span class="o">=</span> <span class="nx">XRegExp</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span> <span class="nx">regex</span><span class="p">);</span>
</span><span class='line'><span class="nx">parts</span>        <span class="c1">// =&gt; [&#39;http://google.com/path/to/file?q=1&#39;, &#39;http&#39;, &#39;google.com&#39;, &#39;/path/to/file&#39;, &#39;q=1&#39;]</span>
</span><span class='line'><span class="nx">parts</span><span class="p">.</span><span class="nx">scheme</span> <span class="c1">// =&gt; &#39;http&#39;</span>
</span><span class='line'><span class="nx">parts</span><span class="p">.</span><span class="nx">host</span>   <span class="c1">// =&gt; &#39;google.com&#39;</span>
</span><span class='line'><span class="nx">parts</span><span class="p">.</span><span class="nx">path</span>   <span class="c1">// =&gt; &#39;/path/to/file&#39;</span>
</span><span class='line'><span class="nx">parts</span><span class="p">.</span><span class="nx">query</span>  <span class="c1">// =&gt; &#39;q=1&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Add-ons et prise en charge d’Unicode</h3>

<p>Dans un web en UTF-8, l&#8217;incapacité de <code>RegExp</code> à gérer Unicode, que ce soient pour les espacements, les lettres ou les chiffres, devient de plus en plus gênante.  <code>XRegExp</code> propose des <em>add-ons</em> pour diverses fonctions, au premier rang desquels la capacité à détecter des <em>catégories Unicode</em>.  À noter que XRegExp gère déjà correctement les espacements Unicode (et notamment l&#8217;espace insécable, code 160) avec <code>\s</code> (donc <code>\\s</code>…).</p>

<p>FIXME: VERIFY THIS \s CLAIM!</p>

<p>De telles catégories sont alors utilisables dans les motifs de correspondance avec la syntaxe <code>\\p{X}</code> (où <code>X</code> est la lettre abrégée de la catégorie) ou <code>\\p{Category}</code> (avec le nom complet).</p>

<ul>
<li><strong>Unicode Base</strong> fournit la catégorie la plus critique&nbsp;: <code>Letter</code> (abréviation <code>L</code>).</li>
<li><strong>Categories</strong> fournit les catégories/propriétés Unicode, telles que <em>Lowercase Letter</em>, <em>Uppercase Letter</em>, <em>Number</em> ou <em>Punctuation</em>.</li>
<li><strong>Scripts</strong> fournit tous les scripts (langues) définis par l’<em>Unicode Multilingual Plane</em>, tels que <em>Latin</em>, <em>Arabic</em>, <em>Greek</em>, <em>Tamil</em>…</li>
<li><strong>Blocks</strong> fournit les blocs Unicode, sortes de sous-ensembles des scripts, tels que <em>InLatin_Extended_A</em> ou <em>InControl_Pictures</em>.</li>
<li><strong>Properties</strong> est un complément de Categories, nécessaire à la prise en charge d’Unicode dite «&nbsp;niveau 1&nbsp;».  On y trouve des séries telles que <em>Alphabetic</em>, <em>WhiteSpace</em>, <em>Ascii</em> ou <em>Assigned</em>.</li>
</ul>


<p>Le site officiel reprend notamment ces exemples&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// Categories</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;\\p{Sc}\\p{N}+&#39;</span><span class="p">);</span> <span class="c1">// Sc: currency symbol, N: number</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Scripts</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;\\p{Cyrillic}&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;[\\p{Latin}\\p{Common}]&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Blocks (use &#39;In&#39; prefix)</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;\\p{InLatinExtended-A}&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;\\P{InPrivateUseArea}&#39;</span><span class="p">);</span> <span class="c1">// Uppercase \P for negation</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;\\p{^InMongolian}&#39;</span><span class="p">);</span> <span class="c1">// Alternate negation syntax</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Properties</span>
</span><span class='line'><span class="nx">XRegExp</span><span class="p">(</span><span class="s1">&#39;\\p{Assigned}&#39;</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Les addons sont à charger après le script de base.  Le site officiel fournit une version totale déjà minifiée, pour ceux qui en ont souvent besoin et préfèrent réduire le nombre de fichiers.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;xregexp.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;addons/unicode/unicode-base.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script&gt;</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">unicodeWord</span> <span class="o">=</span> <span class="nx">XRegExp</span><span class="p">(</span><span class="s2">&quot;^\\p{L}+$&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">unicodeWord</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="s2">&quot;Русский&quot;</span><span class="p">);</span> <span class="c1">// true</span>
</span><span class='line'>  <span class="nx">unicodeWord</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="s2">&quot;日本語&quot;</span><span class="p">);</span> <span class="c1">// true</span>
</span><span class='line'>  <span class="nx">unicodeWord</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="s2">&quot;العربية&quot;</span><span class="p">);</span> <span class="c1">// true</span>
</span><span class='line'><span class="nt">&lt;/script&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="c">&lt;!-- \p{L} is included in the base script, but other categories, scripts,</span>
</span><span class='line'><span class="c">and blocks require token packages --&gt;</span>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;addons/unicode/unicode-scripts.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script&gt;</span>
</span><span class='line'>  <span class="nx">XRegExp</span><span class="p">(</span><span class="s2">&quot;^\\p{Katakana}+$&quot;</span><span class="p">).</span><span class="nx">test</span><span class="p">(</span><span class="s2">&quot;カタカナ&quot;</span><span class="p">);</span> <span class="c1">// true</span>
</span><span class='line'><span class="nt">&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Vous pouvez consulter la <a href="http://xregexp.com/plugins/">liste complète des add-ons XRegExp</a>.</p>

<h2>Quand <strong>ne pas</strong> utiliser les expressions rationnelles&nbsp;?</h2>

<p>On a principalement deux cas&nbsp;:</p>

<ul>
<li>Le besoin est suffisamment simple pour être traité plus rapidement par des moyens textuels classiques&nbsp;; comme un moteur de regex sera toujours plus lourd / plus lent qu&#8217;un traitement textuel basique, recourir à une regex serait alors inutilement bourrin.</li>
<li>Le besoin est trop compliqué pour être traité de façon fiable par les regex&nbsp;; la syntaxe des regex ne permet pas d&#8217;exprimer tout et n&#8217;importe quoi.  Au-delà d&#8217;une certaine limite, on a besoin d&#8217;un moteur plus adapté à la nature du texte examiné, quitte à mélanger les approches entre moteur dédié, textuel basique et regex.</li>
</ul>


<p>On serait dans le premier cas pour détecter, par exemple, la position/présence d&#8217;un texte <strong>fixe</strong> au sein d’une chaîne de caractères.</p>

<p>En revanche, tout traitement basé sur la <em>sémantique</em> du texte est pénible en regex.  Celles-ci opèrent, fondamentalement, au niveau du caractère, pas de la sémantique d&#8217;ensemble.  Quelques exemples classiques devraient vous aider à établir la distinction.</p>

<p>L&#8217;analyse du XML/HTML est, de façon générale, difficile en regex.  On peut bien sûr procéder à quelques extractions simples, comme avec l&#8217;exercice de tout-à-l&#8217;heure sur les liens de résultats naturels chez Google.  Mais corréler deux liens entre eux&nbsp;?  Déterminer si certains liens ont telle ou telle propriété&nbsp;?  Comptabiliser des caractéristiques&nbsp;?  C&#8217;est une autre paire de manches, qui requiert soit un complément d&#8217;analyse sur l&#8217;extraction produite, soit une traversée par un mécanisme plus dédié au problème (en l&#8217;occurrence le DOM, XPath et un algorithme à soi).</p>

<p>Prenons un autre exemple très simple&nbsp;: déterminer la validité d&#8217;une adresse IP classique (une adresse IPv4).  On a besoin de vérifier au minimum deux éléments&nbsp;:</p>

<ol>
<li>On a affaire à 4 nombres séparés par un point</li>
<li>Chaque nombre est entre 0 et 255</li>
</ol>


<p>Le premier point est déjà un peu balourd en regex, qui n&#8217;a pas d&#8217;opérateur «&nbsp;séparé par&nbsp;», et nous obligerait à répéter un motif.  Mais le deuxième point, qui se penche sur la <em>sémantique</em> du nombre, illustre toute la limite des regex.  L&#8217;expression nécessaire montre à quel point on travaille au niveau du caractère&nbsp;:</p>

<pre><code>[01]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]
</code></pre>

<p>Ce qui donne tout de même, pour l&#8217;ensemble&nbsp;:</p>

<pre><code>(?:[01]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]\.){3}[01]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]
</code></pre>

<p>Alors qu&#8217;ici, un traitement textuel classique est amplement suffisant.  Voici une possibilité qui essaie d&#8217;être efficace (au sens où elle «&nbsp;répond&nbsp;» aussitôt que possible)&nbsp;:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">isIPv4</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">components</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="mi">4</span> <span class="o">!=</span> <span class="nx">components</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">index</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">comp</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">components</span><span class="p">[</span><span class="nx">index</span><span class="p">],</span> <span class="mi">10</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">comp</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">comp</span> <span class="o">&gt;</span> <span class="mi">255</span><span class="p">)</span>
</span><span class='line'>      <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Oui, c&#8217;est plus long.  Mais c&#8217;est aussi plus rapide à analyser et comprendre pour quelqu&#8217;un qui ne passe pas ses journées dans les regex…</p>

<h2>Quelques outils pour aider à la construction</h2>

<p>Lorsqu&#8217;on découvre et pratique les regex, un bon outil est souvent utile.  Il doit permettre de visualiser facilement quelles sont les correspondances, quels sont les groupes constitués, etc.  En voici une petite sélection&nbsp;:</p>

<ul>
<li><a href="http://gskinner.com/RegExr/">Regexr</a> est en AIR mais je lui pardonne…  Il permet aussi de sauver ses regex et de consulter une liste notée par les autres internautes (à examiner avec précaution, comme toujours).</li>
<li><a href="http://rubular.com/">Rubular</a> est un outil en ligne basé sur les moteurs Ruby (mais c&#8217;est très similaire à JavaScript + XRegExp).</li>
<li><a href="http://www.regexbuddy.com/">RegexBuddy</a> est un excellent p’tit outil pas mal foutu qui affiche notamment le détail du fonctionnement des correspondances.  En revanche, il a un vrai défaut&nbsp;: il ne marche que sur Windows.</li>
</ul>


<h2>Pour conclure…</h2>

<p>Bon, j&#8217;ai décidément mis <em>beaucoup trop de temps</em> à écrire cet article.  Mais il est finalement là, et j&#8217;espère qu&#8217;il vous aura plu, et donné envie d&#8217;explorer davantage les possibilités qu&#8217;elles offrent pour votre développement au quotidien.</p>

<div data-upcoming-sessions="js-puissant" xstyle="display: none;">
  <h2>Envie d’en apprendre davantage&nbsp;?</h2>
  
  <p>Notre atelier <a href="http://www.js-attitude.fr/js-puissant/">JS Puissant</a> explore en profondeur tous les aspects techniques avancés du langage JavaScript lui-même.  Des méthodes méconnues des types natifs à la programmation fonctionnelle en passant par la <em>truthiness</em> et le fonctionnement des prototypes, cette formation JavaScript vous donne un gros coup de boost dans le développement de vos codes JS quels qu’ils soient.</p>

  <p>Prochaines sessions&nbsp;:</p>
</div>

]]></content>
  </entry>
  
</feed>
