docs(javascript): add warning callout about variable hoisting

This commit is contained in:
Gauthier Daniels 2025-05-13 20:29:14 +02:00
parent ab2a1a8ac3
commit 9344fee81b
3 changed files with 92 additions and 4 deletions

View File

@ -70,3 +70,13 @@ On va donc aborder les sujets suivants :
- Le principe d'asynchrone
Chaque article de cette série sera conçu pour être facilement compréhensible, avec des exemples pratiques et une explication des concepts.
<Callout type="warning" title="Facilement compréhensible !== Facile">
Facilement compréhensible ne veut pas dire que c'est facile à comprendre !
Il y a beaucoup de concepts à assimiler et certains peuvent faire mal au crâne.
Prends ton temps et n'hésite pas à revenir en arrière si tu ne comprends pas quelque chose.
L'idée est de ne surtout pas se précipiter sur les notions suivantes tant que tu n'as pas compris celles abordées dans l'article.
Expérimente et joue avec le code pour plus facilement assimiler !
</Callout>

View File

@ -115,3 +115,43 @@ Les trois mots-clés `var`, `let` et `const` peuvent être utilisés pour décla
<tabs.jsFunctionScope />
Le fonctionnement est le même que pour la portée de bloc, avec cette fois-ci une portée limitée à la fonction _(y compris pour les variables déclarées avec `var`)_.
## Particularités de var
On a vu que `var` n'a pas la possibilité de déclarer des variables avec une portée de bloc, contrairement à `let` et `const`.
Mais il y a une autre particularité à prendre en compte :
- Les variables déclarées avec `var` sont **hoistées**.
Ça signifie que la déclaration de la variable est déplacée en haut de la portée dans laquelle elle a été déclarée.
- Les variables déclarées avec `let` et `const` ne sont pas hoistées.
<Callout type="warning" title="Hoisting">
Le hoisting peut entraîner des comportements inattendus si on essaie d'accéder à une variable avant sa déclaration.
Il est donc préférable de toujours déclarer les variables au début de leur portée.
</Callout>
Petit exemple pour illustrer ça :
<tabs.jsHoisting />
Dans cet exemple, on voit que la variable `x` est déclarée après son utilisation.
Cependant, grâce _(ou à cause, je te laisse choisir !)_ au hoisting, la déclaration de la variable `x` est déplacée en haut de la portée, ce qui permet d'accéder à sa valeur avant sa déclaration.
On peut donc dire que la variable `x` est **undefined** avant sa déclaration, mais elle existe déjà.
On peut donc l'utiliser avant sa déclaration _(enfin, on aura `undefined` comme valeur)_.
C'est un peu déroutant, non ?
<Callout type="warning" title="Utilisation de var">
Promis, c'est la dernière fois que je te dis de ne pas utiliser `var` !
Mais tu l'auras compris, `var` est vraiment très spécial et peut très vite devenir une source de bugs.
</Callout>
## Conclusion
Voilà, c'est "tout" pour cet article sur les fonctions et la portée en JavaScript !
Comme les articles précédents, ça fait beaucoup d'informations.
Encore une fois, prends le temps d'expérimenter et de jouer avec les notions abordées dans cet article avant de passer à la suite !

View File

@ -190,6 +190,7 @@ const jsFunctionScopeSnippets = [
function example() {
let x = 20;
let y = "Bonjour !";
if (true) {
let x = 30;
@ -200,7 +201,8 @@ function example() {
}
example();
console.log(x); // 10`,
console.log(x); // 10
console.log(y); // ReferenceError: y is not defined`,
},
{
name: "Exemple avec const",
@ -210,6 +212,7 @@ console.log(x); // 10`,
function example() {
const x = 20;
const y = "Bonjour !";
if (true) {
const x = 30;
@ -217,10 +220,12 @@ function example() {
}
console.log(x); // 20
console.log(y); // Bonjour !
}
example();
console.log(x); // 10`,
console.log(x); // 10
console.log(y); // ReferenceError: y is not defined`,
},
{
name: "Exemple avec var",
@ -230,6 +235,7 @@ console.log(x); // 10`,
function example() {
var x = 20;
var y = "Bonjour !";
if (true) {
var x = 30;
@ -240,6 +246,37 @@ function example() {
}
example();
console.log(x); // 10
console.log(y); // ReferenceError: y is not defined`,
},
];
const jsHoistingSnippets = [
{
name: "Exemple avec let",
withLineNumbers: true,
codeLanguage: "js",
code: `console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;
console.log(x); // 10`,
},
{
name: "Exemple avec const",
withLineNumbers: true,
codeLanguage: "js",
code: `console.log(x); // ReferenceError: Cannot access 'x' before initialization
const x = 10;
console.log(x); // 10`,
},
{
name: "Exemple avec var",
withLineNumbers: true,
codeLanguage: "js",
code: `console.log(x); // undefined
var x = 10;
console.log(x); // 10`,
},
];
@ -253,4 +290,5 @@ export default {
<Snippet snippets={jsBlockScopeExplanations} />
),
jsFunctionScope: () => <Snippet snippets={jsFunctionScopeSnippets} />,
jsHoisting: () => <Snippet snippets={jsHoistingSnippets} />,
};