Apprendre le JavaScriptPortée des variables & Hoisting

Télécharger la vidéo

Sauter les bases, je connais PHP
La base
Le JavaScript côté navigateur
Les librairies incontournables
Pour aller plus loin
Cas Pratiques (ES2015)

Nous n'allons rien apprendre de nouveau aujourd'hui mais nous allons faire le point sur une notion importante : La portée des variables (scope en anglais).

Les variables ont une portée limitée lorsqu'elles sont déclarées dans une fonction :

var a = function () {
    var b = 3   
}
a()
b // ERREUR, b is not defined

Les fonctions ont une portée locale mais il est possible de faire appel à des variables externes à la fonction

var exterieur = "Salut"
var maFonction = function () {
    exterieur 
    var interieur = 3   
}
maFonction() // Dans cet appel exterieur vaudra "Salut"
interieur // ERREUR, interieur is not defined

Par contre il faut faire attention car si une fonction fait appel à une variable extérieur, elle utilisera la valeur au moment de l'éxécution d'une fonction. C'est ce que l'on appel le contexte, le code à l'intérieur de la fonction disposera des variables disponible lors de son éxécution.

var a = "Salut"
var maFonction = function () {
    return a   
}
maFonction() // "Salut"
a = "Test"
maFonction() // "Test"

Enfin il est aussi important de noter qu'un même nom de variable peut être utilisé dans les différentes portées.

var a = "Salut" // portée globale
var maFonction = function () {
    var a = "demo" // portée locale
    return a 
}
maFonction() // demo 
a // salut
// La variable a définie dans la fonction 
// n'est pas la même que la variable définie
// dans la fonction

Les blocs (for, if...) n'ont pas de portée particulière, ainsi une variable définie dans un for ou un if est disponible en dehors de la boucle / condition.

for (var i = 0; i < 10; i++) {

}
i // 10

L'Hoisting

Le Javascript a une manière particulière de traiter les variables. Par défaut il déplace les déclarations de en haut du contexte courant (fonction courante ou fichier courant)

Ainsi il est possible d'écrire le code suivant sans obtenir d'erreurs :

a // undefined
var a = 3

En lisant ce code on s'attendrait à obtenir une erreur car la variable n'est pas définie au moment de son appel. Le code est en fait compris de la manière suivante :

var a // La déclaration est déplacée en haut
a // undefined 
a = 3

Ce comportement permet par la même occasion d'expliquer la différence entre l'assignation de fonction et la déclaration de fonction.

maFonction() // 3
function maFonction () {
    return 3    
}

La fonction est appellable même si elle n'est déclaré que plus tard dans le script. L'hoisting déplace les déclarations de fonction en haut

// Le code est en fait compris de la manière suivante
// La déclaration est placée au dessus
function maFonction () {
    return 3    
}
// L'appel de la fonction ne pose du coup aucun souci
maFonction() // 3

En revanche si on utilise une assignation on obtient une erreur

maFonction() // ERREUR : maFonction is not a function
var maFonction = function () {
    return 3    
}

Dans ce cas là l'hoisting bouge la déclaration de la variable mais laisse la fonction à sa place

// La variable maFOnction est "hoistée"
var maFonction 
maFonction() // maFonction est undefined donc erreur
// L'assignation reste à sa place (après l'appel)
maFonction = function () {
    return 3    
}

C'est pour cela que l'on préférera généralement créer des fonction en utilisant une assignation de variable afin d'éviter les problèmes qui peuvent être causés par l'hoisting.