Si vous êtes ne serait-ce que légèrement familier avec la programmation (ce que je vous conseille avant de continuer à lire cet article), vous savez que l'utilisation d'une variable se fait en trois temps :

  1. Déclaration
  2. Initialisation
  3. Utilisation

Le tout dans cet ordre précis, même si la déclaration et l'initialisation peuvent parfois se faire sur la même instruction. Il en va de même pour les fonctions dont la déclaration doit toujours prédéder son appel.

Mais avez-vous déjà remarqué que ces affirmations ne sont pas réellement valable en Javascript, et qu'il est possible d'utiliser une variable avant même de l'avoir déclarer, et même chose pour une fonction ?

Cela est rendu possible par une mécanique en JS que l'on appelle le "hoisting" ou "remontée" en français.

Le hoisting

Cette mécanique consiste donc à faire "virtuellement" remonter la déclaration d'une variable (ou d'une fonction) tout en haut de son scope lors de l'analyse du code par le moteur d'interprétation Javascript.

C'est une mécanique automatique et obligatoire qui fait partie de la spécification ECMAScript même si le terme "hoisting" n'y apparait pas en tant que tel.

Pour vous en souvenir, vous pouvez pensez à la locution "ho-hisse" que l'on utilise quand on hisse (qu'on lève, remonte) quelque chose.

Voyons comment celà fonctionne avec des exemples de code :

Pour les variables

Lors de son interprétation du code, le moteur va donc récupérer toutes les déclarations de variables à l'intérieur de chaque scope, pour les faire remonter tout en haut.

Mais attention, il ne remonte que la déclaration, et non l'initialisation, la valeur de la variable sera alors mise à "undefined".

Le code basique suivant :


var x = 3;
console.log(x); /* 3 */

Est alors virtuellement transformé comme ceci :


var x;
x = 3;
console.log(x); /* 3 */

Mais ça ne change pas grand chose me direz-vous ?

Effectivement, dans ce premier exemple le comportement du code ne change pas, mais avec un code comme celui ci-dessous :


console.log(x);
var x = 3;

On devrait s'attendre à ce que l'interpréteur nous renvoie une "ReferenceError" car la variable x est utilisée avant d'être déclarée, mais au lieu de celà, la console affiche "undefined", car la mécanique de hoisting aura virtuellement transformé le code précédent de la manière suivante :


var x;
console.log(x);
x = 3;

La variable aura donc bien été déclarée avant d'être utilisée, mais comme le hoisting ne fonctionne que sur la déclaration et non l'initialisation, x est égal à undefined tant que l'on a pas dépassé la troisième ligne du code précédent !

À noter que même si Javascript permet d'utiliser des variables avant de les déclarer, je vous déconseille de le faire consciemment, ce n'est pas une très bonne pratique.

Attention, le hoisting ne fonctionne qu'avec les variables déclarées avec var, pour celles déclarées avec let ou const, l'interpréteur renverra une erreur car elles sont "remontées" mais non initialisées, pas même avec undefined.

Pour les fonctions

Le hoisting fonctionne aussi avec les fonctions, ce qui vous permet d'organiser votre code de la manière dont vous le souhaitez, sans pour autant avoir à faire attention si une fonction est appelée avant une autre ou non.

Pour reprendre un exemple simple :


f();
function f() { console.log("hello");}

Est virtuellement transformé en :


function f() { console.log("hello");}
f();

Et toutes les déclarations de fonctions viendront donc se placer avant les appels, en haut de leur scope.

Mais attention, celà ne fonctionne pas pour les fonctions anonymes stockées dans des variables, par exemple :


f();
var f = function() { console.log("hello");}

Car la déclaration de la variable f sera bien remontée, mais sa valeur sera temporairement undefined, et l'interpréteur vous enverra donc une erreur du type "f is not function".

Le "Lexical Environment"

Tout au long de cet article je vous ai dit que votre code était modifié "virtuellement", car votre code ne bouge pas, mais les variables, leurs déclarations et leurs valeurs sont stockées dans une structure de données utilisée par le moteur d'interprétation appelé le "Lexical Environment".

Votre code n'est donc pas affecté, c'est la manière dont il est interprété et exécuté qui change, mais la mécanique de hoisting est plus facile à comprendre en voyant le code changer directement, voilà pourquoi je vous l'ai expliqué de cette manière !

J'espère que cet article vous aura été utile, et à bientôt sur le blog !

À propos de l'auteur

Hello, je suis Nicolas Brondin-Bernard, ingénieur web indépendant depuis 2015 passionné par le partage de d'expériences et de connaissances.

Aujourd'hui je suis aussi coach pour développeurs web juniors, tu peux me contacter sur nicolas@brondin.com, sur mon site ou devenir membre de ma newsletter pour ne jamais louper le meilleur article de la semaine et être tenu au courant de mes projets !


Photo par Alex sur Unsplash