Hoisting (remontée)
===================

En JavaScript, l'anglicisme ***hoisting***, qu'on peut traduire en « remontée » (voire plus littéralement en « hissage ») correspond au déplacement de la *déclaration* de fonctions, variables ou classes en haut de leur portée avant l'exécution du code.

Le hissage/la remontée n'est pas un terme défini de façon normative dans la spécification ECMAScript. La spécification définit un groupe de déclarations comme *HoistableDeclaration*, mais cela inclut uniquement les déclarations `function`, `function*`, `async function`, et `async function*`. La remontée est souvent associée aux déclarations `var` d'une façon légèrement différente. Généralement, on regroupe les différents comportements suivants sous ce terme :

1. Être capable d'utiliser la valeur d'une variable dans sa portée avant la ligne où elle est déclarée (« remontée de variable »)
2. Être capable de référence une variable dans sa portée avant la ligne où elle est déclarée, sans que cela déclenche une exception `ReferenceError`, mais où la valeur obtenue est `undefined` (« remontée de déclaration »)
3. La déclaration de la variable entraîne des changements de comportement dans la portée avant la ligne où elle est déclarée.

Les déclarations sans mot-clé préalable sont remontées selon le premier comportement. Les déclarations avec `var` sont remontées selon le deuxième comportement. Enfin, les déclarations avec `let`, `const`, et `class` (parfois désignées comme *déclarations lexicales*) sont remontées selon le troisième comportement.

On peut également considérer que `let`, `const`, et `class` ne déclenchent pas de remontée en raison de la zone morte temporaire qui interdit toute utilisation de la variable avant sa déclaration. Cette différence d'interprétation est acceptable, car le terme n'est pas précisément normé dans la spécification. Toutefois, la zone morte temporaire peut entraîner d'autres modifications observables dans la portée, suggérant ainsi une certaine forme de remontée :


```js
const x = 1;
{
  console.log(x); // ReferenceError
  const x = 2;
}
```


Si la déclaration `const x = 2` n'était pas remontée du tout (autrement si le seul effet produit avait lieu lors de l'exécution), l'instruction `console.log(x)` devrait être capable de lire la valeur de `x` de la portée parente. Toutefois, la déclaration `const` touche quand même la portée dans laquelle elle est définie et l'instruction `console.log(x)` lit la valeur du `x` provenant de la déclaration `const x = 2`, qui n'est pas encore initialisé et déclenche donc une exception `ReferenceError`. Cela étant écrit, on peut considérer l'absence de remontée comme l'absence d'effet de bord utile.

On notera que ce qui suit n'est pas une forme de remontée :


```js
{
  var x = 1;
}
console.log(x); // 1
```


Comme la portée des déclarations `var` n'est pas limitée aux blocs, il n'y a pas d'accès avant déclaration ici.

Pour plus d'informations à ce sujet, voir :

* La remontée pour `var`/`let`/`const` dans le guide sur la grammaire et les types en JavaScript
* La remontée pour `function` dans le guide sur les fonctions
* La remontée pour `class` dans le guide sur les classes (en-US)
Voir aussi
----------

* L'instruction `var`
* L'instruction `let`
* L'instruction `const`
* L'instruction `function`