Comment déclarer des variables en JavaScript ?

May 05, 2019 -9 min de lecture

Javascript

Photo by Wynand van Poortvliet on Unsplash

Le « scope » c’est quoi ?

Le scope, terme anglais qui se traduit chez nous par portée, est un concept d’une importance capitale s’agissant de la création de variables en JavaScript. Cela nous permet de savoir où ces dernières seront utilisables une fois déclarées. Et les variables il y en a souvent beaucoup ! Tant qu’à faire il serait bon de savoir la portée de chaque variable afin d’éviter tout problème non ? Sortons du cadre du développement pour comprendre la portée des variables. Prenons une grande ville comme Lyon. La ville est divisée en arrondissements : 9 au total. La police est également divisée en arrondissement avec des commissariats d’arrondissement. Nous avons donc dans le 7e arrondissement Jean-Eude, policier. Sa portée d’intervention est limitée au 7e. Il ne pourra pas aller dans le 8e arrondissement par exemple. Admettons maintenant qu’il y ait un Jean-Eude également dans la police de Lyon, mais celle du 8e arrondissement cette fois. Peut-on dire que Jean-Eude du 7e et Jean-Eude du 8e sont les mêmes personnes ? Non bien sûr ! Ils remplissent le même rôle, ont le même prénom, mais ce sont bien deux personnes parfaitement différentes. Pour les variables en JavaScript, le principe est exactement le même, la portée de la variable définira son champ d’action. Rappelez-vous de cette analogie pour la suite si vous êtes perdu.

La portée de Var, let et const (scope)

Avant d’entrer dans le vif du sujet, il est bon de rappeler que depuis 2015 il y a 3 façons de déclarer des variables. var, let et const. Chaque méthode à sa spécificité, mais ce qu’il faut savoir c’est que var est la méthode historique (et un peu poussiéreuse ?). Let et const sont les méthodes introduites par la spécification ES 6 de JavaScript. Cette spécification date de 2015, c’est pourquoi on entend aussi souvent parler de ES2015. Je ne vais pas rentrer dans le détail de cette spécification car ce n’est pas le sujet mais sachez simplement qu’elle a eu un grand impact sur le monde du JavaScript.

La portée de var est celle de la fonction.

La portée de var s’étend à la fonction où la variable est déclarée. C’est très important pour bien comprendre la différence entre toutes les façons de déclarer des variables en JavaScript. Petit exemple de déclaration de var dans une fonction :

function setWeight() {
  var weight = 75
}

Maintenant affichons sa valeur dans la console :

function setWeight() {
  var weight = 75
  console.log(weight)
}

Là rien d’incroyable, la valeur affichée dans la console sera bien 75. Maintenant imaginons que nous voulons accéder à cette valeur en hors de la fonction après l’avoir invoquée. Que va-t-il se passer si on exécute ce code à votre avis ?

function setWeight() {
  var weight = 75
}
setWeight()
console.log(weight)

Et bim une erreur ! Uncaught ReferenceError : weight is not defined C’est une erreur parfaitement normale étant donné que la portée de var est limitée à la fonction dans laquelle elle est déclarée. Simple à comprendre n’est-ce pas ? Alors pourquoi avoir inventé deux nouvelles méthodes pour déclarer des variables si celle là marche bien. Est-ce que ce n’est pas se compliquer inutilement la vie ? Et bien non. Voyons un exemple où var peut poser problème. Cela concerne les variables temporaires dont nous n’avons besoin que ponctuellement pour effectuer certaines opérations et qui ne seront utilisées qu’une fois.

var weight = 85
if (weight >= 80) {
  var idealWeight = weight - 4
  console.log(weight) // affiche 85
  console.log(idealWeight) // affiche 81
}
console.log(weight) // affiche 85 weight est une variable globale.
console.log(idealWeight) // affiche 81 ! If n'est pas une fonction :)

Ici on peut donc voir que notre variable temporaire idealWeight est accessible en dehors de notre condition. C’est normal me direz-vous étant donné que if n’est pas une fonction. Mais le problème est maintenant que cette variable temporaire est accessible de partout et va occuper inutilement l’espace de noms de votre programme ce qui pourrait vous obliger à trouver un autre nom de variable pour effectuer une prochaine opération.

let et const ont une portée limitée à leur bloc

C’est à dire que les variables déclarées avec let et const ne peuvent en aucun cas sortir du bloc où elles ont été déclarées. C’est bien tout ça mais qu’est ce qu’on bloc ? Rien de plus simple, un bloc est tout ce qui est compris entre des accolades. Un bloc c’est donc ça : {}. Voyez ça comme un portail en fer forgé qui empêche ces vilaines variables de s’échapper.

Si on reprend l’exemple précédent et que nous le modifions pour remplacer var par const :

const weight = 85
if (weight >= 80) {
  const idealWeight = weight - 4
  console.log(weight) // affiche 85
  console.log(idealWeight) // affiche 81
}
console.log(weight) // affiche 85 weight est une variable globale.
console.log(idealWeight) // affiche une erreur : variable non déclarée.

Comme on peut le voir idealWeight ne fuite pas de sa condition ifet est inaccessible de l’extérieur. C’est bien pour pouvoir réutiliser ce nom dans une une autre partie du code sans cause de problème inopiné.

var, let et const principes de déclaration en JavaScript

Trouver des noms pour les variables n’est pas toujours simple et nous avons souvent envie de réutiliser les mêmes noms pour éviter des erreurs d’étourderies dans notre code en prenant une variable à la place d’une autre. Jusqu’à maintenant, en utilisant var, on pouvait déclarer une variable avec le même nom plusieurs fois dans le même scope. Aucun blocage. Ce qui pouvait s’avérer dangereux car la nouvelle déclaration écrasait la précédente. Ce qui pouvait également entrainer des problèmes dans votre code.

var name = "Bertrand"

// 300 lignes de codes plus loin ...
var name = "Kevin"
console.log(name)
// affiche 'Kevin'. Merci Kevin !

Les mots cléslet et const quant à eux vous empêchent de déclarer plusieurs variables avec le même nom dans le même scope. Ce qui est plutôt pratique comme vous pourrez le constater à l’usage ! Voici un exemple simple pour commencer.

let name = "Bertrand"
let name = "Kevin" //envoi une erreur dans la console

Voyons en quoi le scope limité au bloc peut nous aider à déclarer plusieurs fois une variable avec le même nom sans pour autant causer de problème par la suite.

if (blabla) {
  const name = "Jean"
  console.log(name) // affiche Jean et aucune erreur
}
if (blabla) {
  const name = "Marc"
  console.log(name) // affiche Marc et aucune erreur
}
if (blabla) {
  const name = "Kevin"
  console.log(name) // affiche Kevin et aucune erreur
}
if (blabla) {
  const name = "France"
  console.log(name) // affiche France et aucune erreur
}

Si nous avions utilisé var, nous n’aurions pas eu de problème apparent mais la même variable aurait été écrasée à chaque fois. const et let permettent de créer une variable au début de leur scope. Variable qui s’auto-détruira à la fin du scope où elle est utilisée. Pratique ce principe d’autodestruction des variables non ?

Plus besoin d’IIFE

Parfois, certains noms de variables sont utilisées par plusieurs framework ou par javascript lui même dans certaines circonstances comme la variable name qui dépend de window lorsque nous avons plusieurs fenêtres. Ce qui peut causer une fois encore des problèmes dans votre code. C’est fou comme une simple déclaration de variable peut causer des problèmes divers et variés pas vrai ? 😅 Une solution était jusqu’à présent d’utiliser une fonction IIFE (Immediately Invoked Function Expression). Il s’agit d’une fonction qui s’exécute elle-même sans que nous ayons besoin de l’invoquer. Vous verrez souvent ce type de code dans les framework que vous utilisez lorsque les variables sont déclarées avec var.

;(function() {
  var name = "mathias"
  console.log(name)
})()

Concrètement ça sert à quoi ? Ça permet au framework de s’assurer que vous ne pourrez pas réassigner une variable globale dans votre code par erreur. Imaginons que vous utilisiez un framework qui utilise la variable globale name et qui n’a pas intégré dans son code dans une fonction IIFE. Si après l’import de votre framework vous déclarez vous aussi une variable globale name. Vous allez tout faire exploser en réassignant une variable qui est utilisée par le framework ! L’IIFE intégrée dans le framework permet d’éviter ça. Ça marchait plutôt bien. Mais sincèrement, vous ne trouvez pas ça moche et difficilement lisible ? Etant donné que let et const sont block scoped, on peut remplacer cette bonne vielle IIFE par une technique de petit malin :

{
  const name = "mathias"
  console.log(name)
}

Quoi ??? 😱 C’est quoi ces accolades qui sortent de nul part ? Et bien c’est justement ce par quoi je vous propose de remplacer l’IIFE. Ça peut paraître étrange de prime abord mais cela marche exactement de la même manière. Rappelez vous, let et const ont une portée limitée au bloc où elles sont déclarées la caractéristiques d’un bloc ce sont ses accolades. Beaucoup plus simple n’est ce pas ? Ce n’est pas quelque chose que vous allez utiliser régulièrement mais ça peut toujours être bon de garder ça dans un coin de sa tête si vous rencontrez ça dans framework.

Spécificité de const

const est comme son nom l’indique prévu pour déclarer une variable constante. Autrement dit vous ne pouvez en aucun cas réassigner la valeur de votre variable après l’avoir déclarée.

const age = 28
age = 29 // BIM erreur : vous ne pouvez pas réassigner une variable constante !

Le principe de mutabilité de const

On pourrait facilement s’imaginer que si on assigne un objet ou un array à const, ce dernier ne pourra pas être modifié pas vrai ? C’est ce que semble vouloir dire const du moins. Pourtant ce n’est pas tout à fait ça. Eh oui il faut toujours se méfier des apparences … Lorsque vous déclarez un objet ou un array avec const, vous pouvez tout à fait en changer les propriétés. Tant que vous ne réassignez pas l’objet ou l’array en lui-même. Pour sortir du cadre du développement, si votre const est une Ferrari, vous pouvez lui changer sa couleur, son moteur, faire du tuning, mais en aucun cas vous ne pouvez dire que votre Ferrari est maintenant une Lamborghini. Cela serait toujours une voiture un peu luxueuse, certes, mais pas votre bonne vielle Ferrari. Donc ce n’est pas possible, vous devrez créer une autre const avec votre nouvelle voiture. Compris ?

Comment rendre const vraiment constant ?

Si vous voulez rendre votre object ou votre array vraiment constant vous devez utilisez cette méthode :

const mathias = {
  name: mathias,
  gender: male,
  height: 175,
}
Object.freeze(mathias)

Après ça, il me sera impossible de changer quoi que ce soit dans l’objet que j’ai crée à mon image. Je ne pourrais ni ajouter, ni modifier les propriétés une fois l’objet déclaré. Bien sûr, si je retourne en arrière dans mon code, je pourrais toujours modifier à la main l’objet au moment où je le déclare et ajouter une propriété où la modifier directement. Mais aucun risque de modifier l’objet par accident suite à une condition mal codée par exemple.

Comment déclarer des variables en JavaScript alors ?

Que devez-vous utiliser pour déclarer vos variables ? Je vais vous donner mon opinion.

  1. Utilisez const par défaut pour déclarer toutes vos variables.
  2. Si votre variable doit être modifiée, utilisez let
  3. N’utilisez en aucun cas var … Nous sommes en 2019 bon sang !

Et la compatibilité pour les vieux navigateurs dans tout ça ?

Bon … Il est évident que si vous voulez supporter les vieux navigateurs de type Internet Explorer 7, 8 et 9 let et const vont vous poser des problèmes car ils ne sont pas supportés.

Quoi fait alors si vous devez impérativement supporter ces vieux navigateurs dont la dernière mise à jour remonte à 2011 ? Utiliser une méthode vieille comme Erode ou alors se tourner vers une recette mircale ? La réponse est la recette miracle. Cette recette miracle s’appelle Babel ! C’est un compilateur JavaScript qui vous permet d’utiliser toutes les dernières méthodes de développement JavaScript sans pour autant vous priver du support des anciens navigateurs. Dans un prochain article, je vous expliquerais tout ce que vous devez savoir pour bien débuter avec Babel. En attendant, je vous invite à cliquer sur ce lien pour en apprendre plus : https://babeljs.io/

L’usage des versions 7 à 9 d’internet explorer ne représente que 0,32% des utilisateurs d’internet selon can I use ( https://caniuse.com/#search=const ).Donc n’ayez crainte, utilisez let et const comme si de rien était. Vous ne vous en porterez pas plus mal pour la quasi totalité de vos projets. 👍


Mathias OVIEVE

Rédigé par Mathias OVIEVE, développeur fullstack web et mobile indépendant qui s'efforce de créer des choses utiles et partager ses découvertes.