Éviter le mot-clé « this »
Le mot-clé this
1 est un raccourci parfois utile lorsqu'on écrit du nouveau code JavaScript. Ce mot-clé a cependant la particularité de se comporter différemment du this
en C, C++ ou Java. Il se comporte même différemment selon la version JavaScript ou même si on est en mode strict ou pas.
C'est pourquoi je déteste ce mot-clé. Je fais tout en mon possible pour éviter d'y avoir recours.
Mon argumentaire tient toujours à la maintenance du code. C'est à dire d'être capable de relire mon code six mois plus tard et le comprendre avec le moins d’ambiguïtés possibles.
Je me suis déjà retrouvé avec un code semblable:
/* Considérant <button id='allo'>Allo</button> */
const objet = {
f0 : 'allo',
f1 : function() {
document.getElementById(this.f0).addEventListener('click',objet.f2);
},
f2 : function() {
console.log(this.id)
}
}
objet.f1();
Si on exécute ce code, il va fonctionner, mais le this
dans f1() n'est pas le même this
que dans f2(). Dans f1(), this
réfère à la constante objet
, alors que dans f2(), this
réfère au bouton #allo
.
On pourrait faire la même action en évitant ce mot-clé maudit.
/* Considérant <button id='allo'>Allo</button> */
const objet = {
f0 : 'allo',
f1 : () => {
document.getElementById(objet.f0).addEventListener('click',objet.f2);
},
f2 : e => {
console.log(e.target.id)
}
}
objet.f1();
Ça fonctionne aussi. this
est éliminé. Le code est un peu plus compréhensible. Cependant, la méthode f2(), à moins qu'elle soit appelée ailleurs, devrait être déplacée à l'intérieur de f1(), question d'éviter qu'elle soit visible de l'extérieur de l'objet.
/* Considérant <button id='allo'>Allo</button> */
const objet = {
f0 : 'allo',
f1 : () => {
document.getElementById(objet.f0).addEventListener('click', e => {
console.log(e.target.id)
});
}
}
objet.f1();
Curieusement, ça fait même une méthode plus courte.
Ne pas hésiter à nommer les choses
Il est toujours mieux, pour le suivi et surtout le débogage, de nommer ce sur quoi on travaille. Je veux dire par là de créer des variables pour retenir sa définition.
/* Considérant <button id='allo'>Allo</button> */
document.getElementById('allo').addEventListener('click', e => {
console.log(e.target.id)
});
...est bien, et va écrire le mot « allo » dans la console, si on a l'assurance que le bouton ne contient que le mot Allo.
/* Considérant <button id='allo'><span>Allo</span></button> */
document.getElementById('allo').addEventListener('click', e => {
console.log(e.target.id)
});
... va sûrement planter, car e.target risque fort de pointer vers le span
plutôt que sur le button
.
const allo = document.getElementById('allo');
allo.addEventListener('click', () => {
console.log(allo.id)
});
... ne plantera plus. Non seulement il ne plantera plus, mais en plus, à la relecture, on comprend tout de suite ce qu'on veut faire afficher dans la console.
Je ferais même un petit ajout pour éviter des surprises plus tard:
const allo = document.getElementById('allo');
if (allo) allo.addEventListener('click', () => {
console.log(allo.id)
});
... comme ça, si jamais une modification plus tard ferait disparaître le bouton #allo
, ça ne fera pas planter le code.