Dans cet article je ne vais pas avoir les différents types de variables mais plutôt de la différence qu’il existe entre les différents mot clés.
En javascript il existe 3 mot-clés pour déclarer une variable.
Leurs différences se jouent d’abord sur leur déclaration et leurs affectations.
Pour rappel la déclaration d’une variable correspond au code suivant.
const mavariable;
let mavariable2;
var mavariable3;
Pour rappel une affectation correspond au code suivant.
/**
Debut declaration des variables
**/
const mavariable;
let mavariable2;
var mavariable3;
/**
Fin declaration des variables
**/
/**
Debut affectation des variables
**/
mavariable2 = 3;
mavariable3 = "ROMAIN";
/**
Fin affectation des variables
**/
Le mot clé var
Le mot clé var
est le plus ancien mot clé javascript pour déclarer une variable. Il va déclarer une variable dans le scope courant (global ou function).
Il est possible de redéclarer plusieurs fois la même variable
Il est possible de réaffecter plusieurs fois la valeur d’une variable déclarée avec le mot clé var
.
function mafonction () {
'use strict'
var a = 10;
a = a + 10; // 20
var a = 3;
console.warn(a);
}
Le mot clé let
Le mot clé let
est un nouveau mot clé pour déclarer une variable. il va déclarer une variable dans le scope courant (global, function ou block)
Il est impossible de déclarer plusieurs fois la même variable
Il est possible de réaffecter plusieurs fois la valeur d’une variable déclarée avec le mot clé let
.
function mafonction () {
'use strict'
let a = 10;
a = a + 10; // 20
let a = 3; // Uncaught SyntaxError: Identifier 'a' has already been declared
console.warn(a);
}
Le mot clé const
Le mot clé const
est un nouveau mot clé pour déclarer une variable. il va déclarer une variable dans le scope courant (global, function ou block)
Il est impossible de déclarer plusieurs fois la même variable
Il est impossible de réaffecter plusieurs fois la valeur d’une variable déclarée avec le mot clé const
.
Remarque : ce mot clé fut en fait crée pour déclarer des constantes. il sera forcement initialisé et affecté au même moment. Cependant attention bien que sa réaffectation ne soit pas possible, si votre variable est un objet, rien n’empêche la modification de ses propriétés !
const personne = {
prenom: "romain",
nom: "barraud"
}
personne = {prenom: "usurpateur", nom: "maléfique" } // Uncaught TypeError: Assignment to constant variable.
Cependant si on modifie la propriété prénom de personne alors il ne s’agit pas d’une affectation et ça fonctionne… Est-ce vraiment ce que l’on souhaitait pour notre variable ?
const personne = {
prenom: "romain",
nom: "barraud"
}
personne.prenom= "usurpateur";
personne.nom= "maléfique";
// :(
Je vous donne une astuce pour éviter cela et être sur d’avoir une constante même si la nature de votre variable est un objet vous pouvez utiliser la fonction freeze de Object pour geler votre variable si c’est un objet.
'use strict'
const personne = Object.freeze({
prenom: "romain",
nom: "barraud"
})
personne.prenom= "usurpateur"; //TypeError: Cannot assign to read only property 'prenom' of object '#<Object>'
personne.nom= "maléfique";
La portée
ou scope
détermine la visibilité ou l'accessibilité d'une variable dans la zone de votre code.
Il existe en javascript 4 scopes différents :
Le scope global en javascript est la zone de plus haut niveau, c'est la zone en dehors de tout block et toute fonction.
Cela signifie que toute variable déclarée dans le scope global est accessible et modifiable dans les autres scopes.
Voici un exemple :
const variableGlobale = "toto"; // déclaration dans le scope global
console.log(variableGlobale); // toto
function salut() {
// dans mon scope je peux accéder au scope global
console.warn(`salut ${variableGlobale}`)
}
salut(); // salut toto
Remarque : L’inverse n’est pas vrai, c’est à dire qu’a partir du
global scope
il est impossible d’accéder aux variables des autres scopes (sauf var dans un block scope mais nous verrons ça par la suite).
Les variables déclarées dans des fonctions deviennent locales à cette fonction. Cela veut simplement dire que ces variables ne sont pas accessibles en dehors de cette fonction.
//scope global
function function1() {
//scope local de function1
function nestedFunction() {
//scope local de nestedFunction
}
}
//global scope
function function2() {
//scope local de function2
}
//global scope
A partir du moment où vous déclarez une variable dans une fonction alors elle n'est visible est accessible uniquement dans cette fonction.
Il est alors impossible d'y accéder en dehors de cette fonction.
function shout() {
// je suis dans le function scope de shout
var sentence = "I HAVE A DREAM !";
console.warn(sentence);
}
/* je suis dans le global scope,
je ne peux pas accéder au function scope de shout
*/
console.warn(sentence); // Uncaught ReferenceError: sentence is not defined
Une portée de bloc est la zone à l'intérieur des des instructions conditionnelles if
et switch
ou encore des boucles for
et while
.
Dans l’implémentation ES2015 et supérieur, les mots-clés const
et let
permettent de déclarer des variables dans la portée d'un block, ce qui signifie que ces variables n'existent que dans le bloc correspondant.
function shoutShout() {
if (true) {
// Existe dans le scope de la function
var varDeclaration = "LET IT ALL OUT";
// Existe uniquement dans le block du if
let letDeclaration = 'JUST A YELLOW LEMON TREE !';
// Existe uniquement dans le block du if
const constDeclaration = "COME ON BABY LET'S GO PARTY";
}
console.warn(varDeclaration); // LET IT ALL OUT
console.warn(letDeclaration); // not defined
console.warn(constDeclaration); // not defined
}
shoutShout();
Une portée lexicale en JavaScript signifie qu'une variable définie en dehors d'une fonction peut être accessible à l'intérieur d'une autre fonction définie après la déclaration de la variable.
const title = "Hello world";
(function sayHello() {
console.warn(title); // Hello world
})();
Le mot clé var va permettre de créer une variable dans le global scope
ou le function scope
dans lequel elle a été déclarée. Elle ne se limite pas au block scope
.
function acheterGateau(amount) {
if (amount > 3) {
var hasCake = true;
amount = 0;
}
console.log(hasCake); // Si j'ai assez d'argent alors j'ai le droit au gâteau
}
acheterGateau(10);
function acheterGateau(amount) {
if (amount > 3) {
let hasCake = true;
amount = 0;
}
console.log(hasCake); // hasCake is not defined
}
acheterGateau(10);
// creation de 10 boutons
for (var i = 0; i < 10; i++) {
let btn = document.createElement("button");
btn.innerText = `button ${i}`;
btn.id = `btn-${i}`
document.body.appendChild(btn);
}
// pour chaque bouton on va associer un evenement onclick
for (var i = 0; i < 10; i++) {
let btn = document.getElementById(`btn-${i}`);
btn.addEventListener("click", function() {
// each should log its value.
console.log("Ma valeur est : " + i);
});
}
Remarque: si on clique sur n’importe quel bouton on remarque que la valeur est toujours 10. Mais pourquoi ?
La boucle for va tout simplement créer la variable i dans son scope. Mais c’est un scope de type “block” et par conséquent cela signifie que la variable est déclarée avec le mot clé var est function scope. Elle est en dehors de la boucle for.
On peut vérifier cela il suffit de regarder si la variable existe
console.warn(i) // 10
Pour éviter cela, utiliser le mot clé let suffit, il va créer une variable nouvelle pour chaque tour de boucle.
// pour chaque bouton on va associer un evenement onclick
for (let i = 0; i < 10; i++) {
let btn = document.getElementById(`btn-${i}`);
btn.addEventListener("click", function() {
// each should log its value.
console.log("Ma valeur est : " + i);
});
}
Toutes les variables déclarées en javascript sont Hoisted (hissées) par ce qui s’appelle le Hoisting (Hissage en français)
Ce Hoisting est un comportement par défaut de javascript qui va déplacer toutes les déclarations de votre code au plus haut de leur scope.
Cela signifie en théorie que vous pourriez affecter une valeur a une variable,
puis ensuite dans le même scope l’initialiser.
a = 3;
var a ;
Cela signifie que le code ci-dessus deviendra :
var a;
a = 3;
class
,const
etlet
sont également hissés, la différence est que ces derniers, ne vont pas être initialisé avec la valeurundefined
lors du gats et donc cela provoque une erreur.
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Dans tous les cas gardez en mémoire qu’il vaut mieux en tant que bonne pratique javascript de déclarer toutes les variables au plus haut de votre scope.