DEV Community

Cover image for Aperçus sur la Call Stack, La face cachée de la pile
Benjamin De Mot
Benjamin De Mot

Posted on

Aperçus sur la Call Stack, La face cachée de la pile

Call Stack

JavaScript est un langage single/mono-thread (mono-tâche) et synchrone. C'est-à-dire que l'interpréteur JS exécutera le code ligne par ligne, de la première à la dernière ligne.
Pourquoi ? Parce qu'il n'a qu'une seule call stack (pile d'exécution).

Voyons ce qu'on peut lire sur le MDN à ce sujet :

Une pile d'exécution est le mécanisme d'un interpréteur (comme l'interpréteur de JavaScript sur un navigateur web) pour conserver la trace de son emplacement dans un script qui appelle plusieurs fonctions depuis d'autres fonctions — quelle fonction est en cours d'exécution, quelles fonctions sont appelées depuis cette fonction et doivent être appelées ensuite, etc.

Felix Gerschau dans son article JavaScript Event Loop And Call Stack Explained résume ainsi :

La call stack est un mécanisme qui aide l'interpréteur JavaScript à garder la trace des fonctions que le script appelle.

Garder la trace des fonctions que le script appelle pour y retourner une fois la fonction terminée.

Comment ça se passe ?

Lorsqu'une fonction est appelée, l'interpréteur l'ajoute à la call stack et l'exécute.

Toutes les fonctions appelées par cette première fonction sont ajoutées ou plutôt empilées sur la call stack pour être exécutées le moment venu.

Quand une fonction est terminée, celle-ci est retirée de la call stack et l'interpréteur retourne à la fonction précédente de la pile.

Un exemple concret

Je vais reprendre et traduire l'exemple donné sur la version en-US du MDN:

function greeting() {
   // [1] du code par ici
   sayHi();
   // [2] du code par là
}
function sayHi() {
   return "Hi!";
}

// appelle la fonction 'greeting'
greeting();

// [3] Du code ...
Enter fullscreen mode Exit fullscreen mode

Bon alors, comment ça se passe ici ? Le code sera exécuté ainsi :

1 - L'interpréteur atteint l'appelle de la fonction greeting().

2 - greeting() est ajouté dans la call stack.

Call stack:

  • greeting

3 - Le code de la fonction greeting() est exécuté jusqu'à sayHi().

4 - La fonction sayHi() est appelée.

5 - La fonction sayHi() est empilée sur la call stack.

Call stack:

  • sayHi
  • greeting

6 - Le code de la fonction sayHi() est exécuté jusqu'à sa fin.

7 - Retour à la ligne où la fonction sayHi() a été appelée pour exécuter le reste de la fonction greeting().

8 - sayHi() est retirée de la pile.

Call stack:

  • greeting

9 - Une fois toute la fonction greeting() exécutée, retour à la ligne où elle a été appelée pour exécuter la suite du code.

10 - La fonction greeting() est retirée de la pile.

Call stack:

  • EMPTY

Taille limite de la call stack

On rappelait au début de ce court article que le JS est single thread et synchrone. Le script n'exécutera une instruction que l'une après l'autre. Si une fonction, par exemple, met du temps à retourner un résultat, c'est tout le code qui sera bloqué pour autant de temps. Et dans l'hypothèse d'une fonction récursive telle que celle-ci :

function a() {
    b();
}

function b() {
    a();
}

a();
Enter fullscreen mode Exit fullscreen mode

...on se retrouverait avec une page qui freeze indéfiniment.

C'est pour empêcher cela que les navigateurs ont une call stack de taille limitée. Limite, qui, lorsqu'elle est atteinte, nous gratifie de cette erreur qu'on a tous rencontrée un jour:

Uncaught RangeError: Maximum call stack size exceeded

Latest comments (0)