Blog

JavaScript : ce monde étrange et merveilleux

Illustration de JavaScript : ce monde étrange et merveilleux

JavaScript : Bonnes pratiques et situations incongrues

zoom

Parfois, dans le joyeux open-space de DonkeyCode, entre deux rédactions de lignes de code, des questions existentielles s'imposent à nous.

Codeur anonyme : "Dites-donc les Donkeys : pourquoi doit-on mettre des accolades en JS pour être un gentil codeur ? Ce serait plus rapide sans eux, tout de même ! Et puis tiens, pourquoi trois signes égal ?"

Tandis que je sortais mon étendard de défenseur de code style et que certains préparaient des coktails MoloCodes, je me suis stoppée : je sais que je dois le faire, oui mais pourquoi ?

Ce moment très inspirant nous a permis le 8 mars 2018 de ressortir nos buzzers poussiéreux de notre grenier et d'organiser un Quiz : Bonnes pratiques JS et petites incongruités.

Bien évidemment, nous ne résistons pas à l'envie de vous le partager.

Amis codeurs, enjoy !

QUIZ JS : Bonnes pratiques et petites incongruités

Question 1

Où placer le tag <script/> sur une page HTML ?

  1. Dans le head
  2. A la fin du body
  3. DTC

Réponse

Une page web est lue par le navigateur de haut en bas. La bonne pratique est donc d'insérer le code en dernier élement de la balise body. Ainsi tout le code dit "important" est interpreté en premier et le plus dynamique ensuite.

Bonne pratique

Toujours penser que le contenu est une information prioritaire de la page.

Question 2

Pourquoi ne faut-il pas utiliser la fonction eval() ?

  1. Elle entraine des problèmes de performance.
  2. Parce que c’est le diable qui l’a inventée
  3. eval() peut entrainer des problèmes de sécurité

Réponse

Selon vos croyances, vous pouvez répondre par les 3 propositions ! eval() est une fonction qui exécute du JavaScript. Pour cela, elle démarre le compilateur. Ceci est très gourmand en termes de performance. Enfin, eval() entraîne des problèmes de sécurité car elle permet d'exécuter du code passé en argument avec les passe-droits du navigateur.

Bonne pratique

eval() est interdit car trop gourmand et dangereux.

Question 3

Quelle formule est interdite ?

  1. setTimeout(() => { makeSomething() }, 100);
  2. setTimeout(‘makeSomething()’);
  3. setTimeout(makeSomething);

Réponse

Réponse 2 car un setTimeout ou setInterval appelle la fonction eval() si l'argument passé est une chaine de caractère. Celle-ci, on vous l'accorde : il fallait le savoir :)

Bonne pratique

eval() est interdit et en plus se cache partout ! ;)

Question 4

Que renvoie [1, 1, 1].map(parseInt) ?

  1. [1, 1, 1]
  2. [1, NaN, 1]
  3. undefined

Réponse

La méthode map passe trois arguments à sa callback : la valeur, l'index et le tableau original.

[1, 1, 1].map(parseInt) equivaut donc à

[1, 1, 1].map((value, index, array) => parseInt(value, index, array)))

parseInt() ne prend que deux arguments : une chaîne à parser et sa base, on peut donc oublier l'argument array et se concentrer sur les deux premiers.

Pour l'index 0 : parseInt(1, 0) est interprété comme parseInt(1) et une base autodétectée (10) et retournera donc 1. En revanche, pour notre second élément parseInt tente d'utiliser la base 1, qui est une aberration. Le résultat sera donc NaN.

Résultat : [1, NaN, 1].

Bonne pratique

Il faut systématiquement utiliser parseInt avec deux arguments. En dehors de l'exemple ci-dessus, l'auto-détection de la base est bien souvent néfaste.

Question 5

Que retourne ?

function boom() {
  return 
  1 + 1;
}

Que retourne ?

function bim() {
  return 1 
  + 1;
}

Que retourne ?

var a = 2
function dababoum() {
  return 1
  1 + a ;
}

Réponse

JS interprète de manière différente une ligne suivant si elle se termine par un point-virgule ou non. Donc nos exemples :

boom() => undefined

bim() => 2

dababoum() => 1

Bonne pratique

Il faut toujours terminer sa ligne de code par un ; pour une meilleure lisibilité (et vos copains développeurs vous remercieront !) et pour éviter des interprétations non voulues.

Question 6

Que se passe-t-il ?

if (error)
  log('shit');
  panic();
return response;

Réponse

Qu'une erreur surviennent ou non, la fonction panic() sera toujours executée.

Bonne pratique

Il est nécessaire de toujours encadrer son code par des accolades. Ce type d'erreur arrive plus que l'on ne le croit.

Dans ce cas, le développeur A a voulu gagner un millième de seconde en ne mettant pas d'accolade.

Six mois plus tard, un développeur B ajoute des logs. Comme il doit placer 3 675 logs, il est fatigué et ne fait pas attention aux accolades absentes : c'est le drame !

Aussi soyez gentils, mettez des accolades !

Question 7

Que se passe-t-il ?

try {
  alert(1);
} catch(error) {
  alert(2);
} finally {
  alert(3);
}

Réponse

Fenêtre de dialogue 1 puis une autre avec 3


Que se passe-t-il ?

try {
  throw(1)
} catch(error) {
  alert(2);
} finally {
  alert(3);
}

Réponse

Fenêtre de dialogue 2 puis une autre avec 3


Et maintenant, que se passe-t-il ?

function tryAndReturn() {
  try {
    return 1;
  } catch(error) {
    return 2;
  } finally {
    return 3;
  }
}

alert(tryAndReturn());

Réponse

return 3 : le bloc finallyest toujours exécuté.

Bonne pratique

Il est d'usage d'utiliser des finally pour exécuter du code en cas de succès ou d'erreur, par exemple pour terminer une connexion à une base de données ou fermer un fichier. Il faut juste faire attention au return.

Question 8

Que se passe-t-il ?

alert("string" === typeof "");
alert("string" === typeof String(""));
alert("string" === typeof new String(""));
alert("donkeycode" === String("donkeycode"));
alert("donkeycode" === new String("donkeycode"));

Réponse

"string" === typeof "" => true

"string" === typeof String("") => true

"string" === typeof new String("") => false

"donkeycode" === String("donkeycode") => true

"donkeycode" === new String("donkeycode") => false

new String() change le typage : le resultat sera un object

Bonnes pratiques

Il est recommencé en JS d'appliquer le triple égal pour garantir le typage d'une variable.

Néanmoins il faut faire attention de ne pas instancier les types de base JS car la variable finira avec un type Object.

Question 9

Que se passe-t-il ?

const arr = [0, 1, 2];
alert(arr.length);

Réponse Breaking news : 2 !

Et que se passe-t-il ?

const arr = [0, 1, 2];
arr[10] = 10;
alert(arr.length);

Réponse 11 ! En JS, quand on définit une valeur à un index de tableau, sa taille est modifiée.

Par ailleurs la méthode map ne prend en compte que les éléments associés à une valeur (y compris undefined) : avec arr.map(a => console.log(a)); on verra 0, 1, 2 et 10. Les autres index sont empty

Bonne pratique

On évite de modifier un élément d'un tableau dont l'index est supérieur à la longueur de celui-là.

Conclusion

  • Un script dans le body, ce n'est pas sale ! Il faut penser priorisation d'information
  • eval() est à éviter absoluement !
  • setTimeout() / setInterval() : oui mais avec une fonction en argument
  • parseInt() s'accompagne toujours de sa base
  • Celui qui ne met pas de point-virgule ni d'accolade ne travaille pas chez DonkeyCode !
  • On n'utilisera plus var mais plutôt :
  • const en priorité : arrayobject, ou booleanstringnumber non changeants
  • let pour les autres variables
  • Utilisation des === indispensable