<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog personnel de Jérémy TRUFIER &#187; optimisation</title>
	<atom:link href="http://www.jeremy-trufier.net/tag/optimisation/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeremy-trufier.net</link>
	<description>Un blog utilisant WordPress</description>
	<lastBuildDate>Fri, 01 Apr 2011 16:50:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Javascript et les trois manières de faire un IF</title>
		<link>http://www.jeremy-trufier.net/2010/09/29/javascript-et-les-trois-manieres-de-faire-un-if/</link>
		<comments>http://www.jeremy-trufier.net/2010/09/29/javascript-et-les-trois-manieres-de-faire-un-if/#comments</comments>
		<pubDate>Wed, 29 Sep 2010 14:30:11 +0000</pubDate>
		<dc:creator>Jérémy TRUFIER</dc:creator>
				<category><![CDATA[Comparatifs]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[Informatique]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[comparaison]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[les différents if]]></category>
		<category><![CDATA[navigateurs]]></category>
		<category><![CDATA[opera]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[réduction taille]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.jeremy-trufier.net/?p=202</guid>
		<description><![CDATA[La syntaxe du javascript n&#8217;est régie par aucune norme prédéfinie, ainsi n&#8217;importe qui peut programmer de la manière qu&#8217;il veut. Pour ma part ces derniers temps je  me suis penché sur l&#8217;optimisation de mon code javascript en me basant sur trois points : gagner du temps en programmant =&#62; code simple à écrire, facilement lisible pour [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-240" title="if ou else" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/if-else1.png" alt="" width="149" height="141" /></p>
<p>La syntaxe du javascript n&#8217;est régie par aucune norme prédéfinie, ainsi n&#8217;importe qui peut programmer de la manière qu&#8217;il veut.</p>
<p>Pour ma part ces derniers temps je  me suis penché sur l&#8217;optimisation de mon code javascript en me basant sur trois points :</p>
<ul>
<li>gagner du temps en programmant =&gt; code simple à écrire, facilement lisible pour y revenir plus tard</li>
<li>optimisation de la vitesse d’exécution du code</li>
<li>diminution de la taille de notre javascript =&gt; les compresseurs automatiques existent, mais leurs algorithmes ne permettent pas de tout réduire, un code faisant 150ko pourra être réduit à 40ko, mais ce même code programmé d&#8217;une autre façon pourra très bien être réduit à 30ko. Bien entendu, nous ne sommes plus aussi attentif qu&#8217;avant sur la taille de nos fichiers grâce à l&#8217;ADSL, mais n&#8217;oublions pas nos clients mobile, et surtout la charge en moins que la bande passante de notre serveur évitera.</li>
</ul>
<p><span id="more-202"></span></p>
<h2>Les Trois &laquo;&nbsp;if&nbsp;&raquo;</h2>
<p>Afin de connaitre facilement duquel on parle dans la suite de l&#8217;article, j&#8217;ai décidé de les nommer de cette façon : if explicite, if implicite et if ternaire. Je rajouterai bientôt le Switch dans ces graphiques.</p>
<p>Attention tout de même, ils ne permettent pas tous la même chose !</p>
<h3>If Explicite</h3>
<p>Bon celui-là tout le monde le connait, et si vous ne le connaissez pas, je pense que vous vous êtes trompé de site <img src='http://www.jeremy-trufier.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  !</p>
<pre class="brush: jscript; title: ;">if ( variable1 === 'valeur 1' ) {
//alors
} else {
//sinon
}</pre>
<p>&laquo;&nbsp;Ah ah, le noob&#8230; il a même pas mit les elseif !!!&nbsp;&raquo;<br />
En fait les &laquo;&nbsp;else if&nbsp;&raquo; sont simplement des &laquo;&nbsp;else&nbsp;&raquo; ou dans le bloc nous avons un &laquo;&nbsp;if&nbsp;&raquo;, mais comme vous le savez, nous pouvons omettre les accolades lorsque le bloc suivant ne contient qu&#8217;une instruction.</p>
<p>Ainsi le code suivant :</p>
<pre class="brush: jscript; title: ;">if ( variable1 === 'valeur 1' ) {
//alors
} else if ( variable1 === 'valeur 2' ) {
//sinon si
}
else{
//sinon
}</pre>
<p>est l&#8217;équivalent de celui-ci :</p>
<pre class="brush: jscript; title: ;">
if ( variable1 === 'valeur 1' ) {
//alors
} else {
if ( variable1 === 'valeur 2' ) {
//sinon si
}
else{
//sinon
}
}
</pre>
<p>Voici un petit graphe qui compare la vitesse d&#8217;exécution de cette structure afin de faire une simple affectation.<br />
Cette structure contient 1 if, 4 elseif et 1 else, chaque niveau correspond à un if/else différent (level 0=if, level 5=else).</p>
<p style="text-align: center;"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/Capture-2010-09-26-à-12.19.20.png" rel="lightbox[202]"><img class="size-medium wp-image-218 aligncenter" title="Graphique de comparaison d'un If explicite sur des navigateurs PC" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/Capture-2010-09-26-à-12.19.20-300x170.png" alt="" width="300" height="170" /></a></p>
<p style="text-align: left;">Et là grande surprise, remarquez comme la dernière version de firefox, l&#8217;air de rien, arrive en tête de se classement ! Firefox n&#8217;étant pourtant pas réputé pour son moteur de javascript très performant, il arrive a se démarquer des autres sur les tests conditionnels/affectation de façon impressionnante. Safari 5 en version PC est quant à lui, un peu à la traîne, je rajouterai bientôt le même comparatif en utilisant les navigateurs sous OS X. Opera qui a également amélioré son moteur javascript, se trouve dans la même unité de grandeur que les autres avec un peu d&#8217;avance par rapport à Chrome. J&#8217;ai été déçu par les résultats de ce dernier sur ce test. Finalement Internet Explorer 9, pourtant prometteur <a title="IE9 béta a dopé son moteur Javascript" href="http://www.jeremy-trufier.net/2010/09/21/ie9-beta-a-dope-son-moteur-javascript/">(voir mon autre test)</a> ne se met pas non plus en avant sur ce test.</p>
<p style="text-align: left;">
<h3>If Ternaire</h3>
<p>Beaucoup de gens l&#8217;utilisent également, il est très pratique et surtout lisible quand il s&#8217;agit de faire un choix entre deux valeurs en inline. Il marchera même en plein milieu d&#8217;une chaîne de caractère ou d&#8217;une instruction.</p>
<pre class="brush: jscript; title: ;">
var nb=5,
	s='Il y a '+nb+' utilisateur'+((nb&gt;1)?'s':'')+' sur ce site'; //ici 5 est supérieur à 2, nous aurons donc un S à la fin de utilisateurs
</pre>
<p>Bon pas trop mal n&#8217;est-ce pas, mais ça devient très vite imbuvable et illisible si on veut faire un peu plus compliqué :</p>
<pre class="brush: jscript; title: ;">
var nb=5,
	s='il y a '+((nb&gt;1)?nb+' utilisateurs':((nb&gt;0)?1:'aucun')+' utilisateur')+' sur ce site';
</pre>
<p>Au niveau du petit combat entre navigateur :</p>
<div id="attachment_224" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-ternaire.png" rel="lightbox[202]"><img class="size-medium wp-image-224" title="Graphique de comparaison d'un If ternaire sur les navigateurs PC" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-ternaire-300x192.png" alt="" width="300" height="192" /></a><p class="wp-caption-text">Graphique de comparaison d&#39;un If ternaire sur les navigateurs PC</p></div>
<p>Toujours firefox de loin en tête, pas de majeurs changement par rapport au test précédent.</p>
<h3>If Implicite</h3>
<p>Alors là, nous allons un peu jouer avec les spécificités du langage Javascript. Cette structure conditionnelle est très peu utilisée, un peu moins lisible que le if explicite ou ternaire dans certains cas, mais beaucoup plus rapide à écrire et à lire dans d&#8217;autres.</p>
<p>Imaginons que nous avons un objet appelé &laquo;&nbsp;O&nbsp;&raquo;, et que nous voudrions appeler la fonction &laquo;&nbsp;f&nbsp;&raquo; de cet objet seulement dans le cas où cette fonction existe, ainsi avec un if explicite nous ferions :</p>
<pre class="brush: jscript; title: ;">
if(O.f)
	O.f();
</pre>
<p>Maintenant en if implicite :</p>
<pre class="brush: jscript; title: ;">
O.f &amp;&amp; O.f();
</pre>
<p>Bon on ne gagne pas grand chose ici n&#8217;est-ce pas ?</p>
<p>Imaginons une petite fonction getter/setter pour des inputs :</p>
<pre class="brush: jscript; title: ;">
function iV(idt,v){
	var el=document.getElementById(idt) || {};
	el= (el.value &amp;&amp; el) || {value:''};
	return el.value =  (arguments&gt;1 &amp;&amp; v) || el.value;
}
</pre>
<p>Ce code est un exemple extrême peu optimisé, mais qui donne un bon aperçu de la syntaxe.<br />
Que fait le code ?<br />
ligne 2 : on récupère notre input et s&#8217;il n&#8217;existe pas, on retourne simplement un objet vierge pour ne pas générer une erreur javascript ensuite.<br />
ligne 3 : si notre objet contient un champs value, c&#8217;est bon, donc on retourne notre objet, sinon, on retourne un objet vierge contenant un champs value pour ne pas non plus générer une erreur javascript ensuite.<br />
ligne 4 : si nous avons plus d&#8217;un argument, alors nous affectons notre deuxième argument (v) au champs value de notre input, sinon, on ne change rien, on le réaffecte lui-même. Finalement on retourne tout ça !</p>
<p>Pourquoi ne pas directement à la ligne 3 passer la &laquo;&nbsp;value&nbsp;&raquo; dans une variable ?<br />
Tout simplement car la &laquo;&nbsp;value&nbsp;&raquo; n&#8217;est pas un objet, et ici ce ne sera pas le pointeur qui sera copié, mais la valeur. Il ne faut pas oublier qu&#8217;en javascript les objets sont passé par référence et String/int/Bool/&#8230; sont passé par valeur.</p>
<p>Nous enregistrons également notre élément dans une variable el, car document.getElementById prend du temps à s’exécuter, étant donné qu&#8217;elle parcourt le Dom de notre page. Ainsi on ne l&#8217;appelle ici qu&#8217;une seule fois.</p>
<p>Un code équivalent avec une structure if/else :</p>
<pre class="brush: jscript; title: ;">
function iV(idt,v){
	var el;

	if(el=document.getElementById(idt)){
		if(arguments.length&gt;1){
			if(el.value){
				return el.value=v;
			}
			else
				return v;
		}
		else if(el.value)
			return el.value;
	}
	else if(arguments.length&gt;1)
		return v;
	return false;
}
</pre>
<p>Si on traduit ligne à ligne en structure conditionnelle implicite :</p>
<pre class="brush: jscript; title: ;">
function iV(idt,v){
    var el;
    return (
        (el=document.getElementById(idt)) &amp;&amp; (
            (
                arguments.length&gt;1 &amp;&amp; (
                    (el.value &amp;&amp; (el.value=v))
                    || v
                )
            )
            || el.value
        )
    )
    || (arguments.length&gt;1 &amp;&amp; v)
    || false;
}
</pre>
<p>En réduisant :</p>
<pre class="brush: jscript; title: ;">
function iV(idt,v){
    var el;
    return ((el=document.getElementById(idt)) &amp;&amp; ((arguments.length&gt;1 &amp;&amp; ( (el.value &amp;&amp; (el.value=v)) || v)) || el.value)) || (arguments.length&gt;1 &amp;&amp; v) || false;
}
</pre>
<p>Maintenant les deux codes compressés :</p>
<pre class="brush: jscript; title: ;">
function iV(a,v){var b;if(b=document.getElementById(a)){if(arguments.length &gt;1){if(b.value){return b.value=v}else return v}else if(b.value)return b.value} else if(arguments.length&gt;1)return v;return false}
</pre>
<p>et</p>
<pre class="brush: jscript; title: ;">
function iV(a,v){var b;return((b=document.getElementById(a))&amp;&amp;((arguments .length&gt;1&amp;&amp;((b.value&amp;&amp;(b.value=v))||v))||b.value))|| (arguments.length&gt;1&amp;&amp;v)||false}
</pre>
<p>Et on se retrouve avec un code à 156 caractères en if implicite et un à 202 caractères en if explicite, soit 25% de moins ce qui est énorme.</p>
<p>Je pense notamment à ce concours : <a href="http://10k.aneventapart.com/">10K Apart</a> dont le but était de faire une application web impressionnante, dont la taille serait la plus petite possible, avec une limite de 10kb. Avec cette méthode, j&#8217;ai réussi à rapporter le code du gagnant de 6,9kb à 4,1kb. Plutôt sympas non ? pour perdre son temps <img src='http://www.jeremy-trufier.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  !</p>
<p>Vous l&#8217;aurez donc compris, ce code est très utile pour des structures très simple, tel que pour vérifier l&#8217;existence d&#8217;attributs d&#8217;objets, mais très dur à lire dès qu&#8217;on arrive dans des structures complexes (et sans habitude <img src='http://www.jeremy-trufier.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). Toutefois, nous nous rapprochons d&#8217;un langage plus brut, et il est donc plus petit au final. Je pense notamment au</p>
<p>Voici pour le petit graphique :</p>
<div id="attachment_225" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-implicit.png" rel="lightbox[202]"><img class="size-medium wp-image-225" title="Graphique de comparaison d'un If Implicite sur les navigateurs PC" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-implicit-300x193.png" alt="" width="300" height="193" /></a><p class="wp-caption-text">Graphique de comparaison d&#39;un If Implicite sur les navigateurs PC</p></div>
<p>Ici encore nous tombons sur des résultats sensiblement pareils. Ce qui va être intéressant maintenant, c&#8217;est au sein d&#8217;un navigateur, quel if est le plus rapide ? C&#8217;est l&#8217;objet de la partie suivante.</p>
<h2>Comparaison des &laquo;&nbsp;If&nbsp;&raquo;</h2>
<p>Voici les comparaisons des trois If par navigateur, les graphiques suffisent à eux-même.</p>
<div id="attachment_229" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-firefox.png" rel="lightbox[202]"><img class="size-medium wp-image-229" title="Benchmark if sous Firefox 3.6 PC" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-firefox-300x208.png" alt="" width="300" height="208" /></a><p class="wp-caption-text">Benchmark if sous Firefox 3.6 PC</p></div>
<div id="attachment_230" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-ie.png" rel="lightbox[202]"><img class="size-medium wp-image-230" title="Benchmark if sous Internet Explorer 9" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-ie-300x208.png" alt="" width="300" height="208" /></a><p class="wp-caption-text">Benchmark if sous Internet Explorer 9</p></div>
<div id="attachment_231" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-opera.png" rel="lightbox[202]"><img class="size-medium wp-image-231" title="Benchmark if sous Opera 10.62" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-opera-300x200.png" alt="" width="300" height="200" /></a><p class="wp-caption-text">Benchmark if sous Opera 10.62</p></div>
<div id="attachment_232" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-safari.png" rel="lightbox[202]"><img class="size-medium wp-image-232" title="Benchmark if sous Safari 5 PC" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-safari-300x208.png" alt="" width="300" height="208" /></a><p class="wp-caption-text">Benchmark if sous Safari 5 PC</p></div>
<div id="attachment_233" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-chrome.png" rel="lightbox[202]"><img class="size-medium wp-image-233" title="Benchmark if sous Chrome 6 PC" src="http://www.jeremy-trufier.net/wp-content/uploads/2010/09/3if-chrome-300x208.png" alt="" width="300" height="208" /></a><p class="wp-caption-text">Benchmark if sous Chrome 6 PC</p></div>
<p>Ainsi nous pouvons voir, qu&#8217;il faudra privilégier les If Implicites aux If Ternaires qui sont fortement moins performants sur la plupart des navigateurs.<br />
Il est ici impossible de tenir compte de Firefox étant donné l&#8217;ordre de grandeur 10 fois moindre, les différences entre les trois if ne sont donc, sur ce navigateur, pas représentatives.</p>
<h2>Ce qu&#8217;il faut retenir</h2>
<ul>
<li>En règle générale, utiliser des <strong>if explicites</strong> <em>(lisibilité, performance, au détriment du poids)</em></li>
<li>Utiliser des <strong>If implicites</strong> en lieu et place des <strong>If ternaires</strong> moins performants <em>(performance)</em></li>
<li>Utiliser des <strong>If implicites</strong> pour une simple vérification de valeur et une action ou une autre <em>(lisibilité, performance, nombre de caractère plus petit)</em></li>
<li>Pour les grandes structures conditionnelles : utiliser des <strong>If Explicites</strong> à moins de vouloir à tout pris gagner des kilo-octets sur le poids du fichier script<em> (lisibilité)</em></li>
</ul>
<p>A bientôt !</p>
<p>(PS: je n&#8217;ai pas corrompu les résultats de Firefox, mon navigateur favori étant Safari)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremy-trufier.net/2010/09/29/javascript-et-les-trois-manieres-de-faire-un-if/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->