Lors de Devoxx France 2013 j’ai beaucoup apprécié le retour de Florian Boulay intitulé “Javascript pour les développeurs Java : quels sont les pièges à éviter ?” . Dans cette conférence, il nous a fait part des surprises qu’il a rencontré et des solutions qu’il a pu apporter.
Portée des variables
Si on ne met pas var devant une variable celle-ci est alors globale.
Solution : on met toujours var qui force une portée locale.
var foo = 'global' function funct() { var foo = 'local'; bar = 'global'; console.log(foo); // 'local' console.log(bar); // 'global' } funct(); console.log(foo); // 'global' console.log(bar); // 'global' instanciée depuis funct()
Pour une meilleure lisibilité et pour identifier facilement que l’on utilise bien des variables locales, on peut systématiquement déclarer ses variables en début de méthode.
Isolation du code
Pour éviter de déclarer des méthodes au niveau global, on les isole de la façon suivante :
(function() { var foo = 'hello'; //... })();
Cela s’appelle le module pattern.
Celui-ci permet d’éviter d’utiliser le namespace global pour la déclaration de la fonction. On évite ainsi les conflits de noms qui pourraient survenir.
Le module pattern permet aussi d’émuler le concept de classe de la manière suivante:
var module = (function() { var exposedObject = {}, privateVariable = 1; function privateMethod() { // méthode privée } exposedObject.publicProperty = true; exposedObject.publicMethod = function() { // méthode exposée } return exposedObject; })(); module.publicMethod();
Tout ce qui n’est pas ajouté à l’objet exposedObject reste invisible “à l’extérieur”, c’est ce qui différencie les méthodes privées des méthodes publiques du module.
Objets
Pour la déclaration d’objets, Florian conseille de s’en tenir à la notation littérale pour plus de clarté.
var obj = { prop : true, funct : function() { return 'me'; } };
Quand utiliser new ?
Que doit-on utiliser ?
var myvar1 = ApiObject();
ou
var myvar1 = new ApiObject();
La convention (tacite) : il faut utiliser new quand la fonction commence par une majuscule.
Si la méthode utilise this alors il faut utiliser new.
L’objet référencé par this dépend du contexte d’exécution.
Egalité
Lorsque l’on compare 2 objets avec ‘’, ceux-ci sont éventuellement modifiés afin de pouvoir être comparés. L’intention est bonne mais est source de nombreux problèmes. Afin de lever toute ambiguïté on utilisera ‘=’ (triple égal) qui ne transformera pas les opérandes au préalable. Ainsi, si on compare 2 objets de types différents, on est alors certain que la triple égalité ne renverra jamais true.
typeof versus instanceof
Les 2 opérateurs servent le même but mais:
– typeof renvoie une chaine de caractères
– instanceof renvoie des informations plus complètes sur le type
On utilisera typeof avec les types simples du langage.
On utilisera instanceof avec les types customs
Les Type Wrappers
Ils n’apportent rien et gênent la lisibilité. On leur préférera une écriture claire et concise.
new Object() => {} new Array() => [] new Number(42) => 42 new String('42') => '42' new Boolean(true) => true new Regexp('.') => /./
Convertir un texte en nombre
parseInt peut donner des résultats surprenant en parsant une chaîne de caractères. En effet les lettres sont filtrées de manière transparentes lors de la conversion.
pour lever l’ambiguïté on peut préfixer la chaîne à parser par un +, on aura ainsi davantage de NaN (Not a Number) remontés.
Mon collègue Arthur Weber me signale également qu’on peut préfixer les variables à parser avec ‘~~’ ce qui en cas d’erreur renverra la valeur par défaut 0.
~~'foo'; // 0 parseInt('foo', 10); // NaN
Ce qui évite le type de code suivant
if (x === NaN ) x = 0;
Slides de la présentation : http://www.slideshare.net/FlorianBoulay/javascript-pour-lesdeveloppeursjava
Pour aller plus loin, découvrez notre formation JavaScript : http://www.ippon.fr/formation/javascript