Les informations contenues dans cet article sont utiles pour comprendre les anciens scripts.
Ce nâest pas ainsi que nous Ă©crivons du nouveau code.
Dans le tout premier chapitre qui parle des variables, nous avons mentionné trois façons pour déclarer une variable :
letconstvar
La déclaration var est similaire à let. La plupart du temps, nous pouvons remplacer let par var ou vice-versa et nous attendre à ce que les choses fonctionnent :
var message = "Hi";
alert(message); // Hi
Mais en interne, var est une bĂȘte trĂšs diffĂ©rente, originaire de trĂšs vieux temps. Il nâest gĂ©nĂ©ralement pas utilisĂ© dans les scripts modernes, mais se cache toujours dans les anciens.
Si vous ne prĂ©voyez pas de rencontrer de tels scripts, vous pouvez mĂȘme sauter ce chapitre ou le reporter.
Dâun autre cĂŽtĂ©, il est important de comprendre les diffĂ©rences lors de la migration dâanciens scripts de var vers let, pour Ă©viter des erreurs Ă©tranges.
âvarâ nâa pas de portĂ©e limitĂ©e aux blocs
Les variables, déclarées avec var, ont une portée fonction ou globale. Ils sont visibles à travers des blocs.
Par exemple :
if (true) {
var test = true; // utilise "var" au lieu "let"
}
alert(test); // vrai, la variable existe aprĂšs if
Comme var ignore les blocs de code, nous avons une variable globale test.
Si nous aurions utilisĂ© let test au lieu de var test, la variable aurait seulement Ă©tĂ© visible Ă lâintĂ©rieur de if :
if (true) {
let test = true; // utilise "let"
}
alert(test); // ReferenceError: test is not defined
MĂȘme principe pour les boucles : var ne peut pas ĂȘtre locale pour les blocs ni les boucles :
for (var i = 0; i < 10; i++) {
var one = 1;
// ...
}
alert(i); // 10, "i" est visible aprĂšs la boucle, c'est une variable globale
alert(one); // 1, "one" est visible aprĂšs la boucle, c'est une variable globale
Si un bloc de code est Ă lâintĂ©rieur dâune fonction, var devient une variable Ă lâĂ©chelle de la fonction :
function sayHi() {
if (true) {
var phrase = "Hello";
}
alert(phrase); // fonctionne
}
sayHi();
alert(phrase); // ReferenceError: phrase is not defined
Comme nous pouvons le constater, var pĂ©nĂštre Ă travers if, for ou les autres blocs de code. Câest parce que, il y a longtemps, les blocs de JavaScript nâavaient pas dâenvironnements lexicaux, et var est un vestige de ce dernier.
âvarâ tolĂšre les redĂ©clarations
Si nous dĂ©clarons la mĂȘme variable avec let deux fois dans la mĂȘme portĂ©e, câest une erreur :
let user;
let user; // SyntaxError: 'user' has already been declared
Avec var, nous pouvons redéclarer une variable autant de fois que nécessaire. Si nous utilisons var avec une variable déjà déclarée, elle est simplement ignorée :
var user = "Pete";
var user = "John"; // ce "var" ne fait rien (déjà déclaré)
// ...ça ne déclenche pas d'erreur
alert(user); // John
âvarâ les variables peuvent ĂȘtre dĂ©clarĂ©es sous leur utilisation
Les déclarations var sont traitées quand la fonction commence (ou quand le script commence pour le cas global).
En dâautres mots, les variables var sont dĂ©finies au dĂ©but de la fonction, peu importe oĂč la dĂ©finition se retrouve (prĂ©sumant que la dĂ©finition nâest pas dans une fonction imbriquĂ©e).
Alors ce code :
function sayHi() {
phrase = "Hello";
alert(phrase);
var phrase;
}
sayHi();
âŠest techniquement identique Ă ceci (nous avons simplement bougĂ© var phrase du code juste avant) :
function sayHi() {
var phrase;
phrase = "Hello";
alert(phrase);
}
sayHi();
âŠou mĂȘme ceci (souvenez-vous, les blocs de code sont ignorĂ©s) :
function sayHi() {
phrase = "Hello"; // (*)
if (false) {
var phrase;
}
alert(phrase);
}
sayHi();
Certains nomment ce comportement âhoistingâ (hisser) parce que toutes les var sont âhoistedâ (hissĂ©es) jusquâen haut de la fonction.
Ainsi, dans lâexemple ci-dessus, la branche if (false) ne sâexĂ©cute jamais, mais cela nâa pas dâimportance. La var quâelle contient est traitĂ©e au dĂ©but de la fonction, donc au moment de (*) la variable existe.
Les déclarations sont hissées, mais les affectations ne le sont pas.
Cela est mieux démontré avec un exemple :
function sayHi() {
alert(phrase);
var phrase = "Hello";
}
sayHi();
La ligne var phrase = "Hello" contient deux actions :
- Déclaration de la variable
var - Affectation de la variable
=.
La dĂ©claration est traitĂ©e au dĂ©but de lâexĂ©cution de la fonction (âhoistedâ), mais lâaffectation fonctionne toujours Ă lâendroit oĂč elle apparaĂźt. Essentiellement, le code fonctionne comme ceci :
function sayHi() {
var phrase; // déclaration fonctionne au début...
alert(phrase); // undefined
phrase = "Hello"; // ...affectation - quand l'exécution y parvient.
}
sayHi();
Parce que toutes les dĂ©clarations var sont traitĂ©es au dĂ©but de la fonction, nous pouvons y faire rĂ©fĂ©rence nâimporte oĂč. Mais les variables sont indĂ©finies jusquâaux affectations.
Dans les deux exemples au dessus, alert fonctionne sans erreur parce que la variable phrase existe. Mais sa valeur nâest pas encore affectĂ©e, alors cela donne undefined.
IIFE
Comme par le passĂ©, il nây avait que var, et quâil nâa pas de visibilitĂ© au niveau du bloc, les programmeurs ont inventĂ© un moyen de lâimiter. Ce quâils ont fait a Ă©tĂ© appelĂ© âexpressions de fonction immĂ©diatement invoquĂ©esâ (en abrĂ©gĂ© IIFE).
Ce nâest pas quelque chose que nous devrions utiliser de nos jours, mais vous pouvez les trouver dans dâanciens scripts.
Un IIFE ressemble Ă ceci :
(function() {
var message = "Hello";
alert(message); // Hello
})();
Ici, une fonction expression est créée et immĂ©diatement appelĂ©e. Ainsi, le code sâexĂ©cute immĂ©diatement et possĂšde ses propres variables privĂ©es.
La fonction expression est entourĂ©e de parenthĂšses (fonction {...}), car lorsque JavaScript rencontre "function" dans le flux de code principal, il le comprend comme le dĂ©but dâune fonction dĂ©claration. Mais une fonction dĂ©claration doit avoir un nom, donc ce type de code donnera une erreur :
// Essayons de déclarer et d'appeler immédiatement une fonction
function() { // <-- SyntaxError: Les instructions de fonction nécessitent un nom de fonction
var message = "Hello";
alert(message); // Hello
}();
MĂȘme si nous disons : âdâaccord, ajoutons un nomâ, cela ne fonctionnera toujours pas, parce que JavaScript ne permet pas dâappeler immĂ©diatement les fonctions dĂ©clarations :
// erreur de syntaxe Ă cause des parenthĂšses ci-dessous
function go() {
}(); // <-- ne peut pas appeler la fonction déclaration immédiatement
Ainsi, les parenthĂšses autour de la fonction sont une astuce pour montrer Ă JavaScript que la fonction est créée dans le contexte dâune autre expression, et donc câest une fonction expression : elle nâa pas besoin de nom et peut ĂȘtre appelĂ©e immĂ©diatement.
Il existe dâautres façons que les parenthĂšses pour dire Ă JavaScript que nous souhaitons une fonction expression :
// Façons de créer une IIFE
(function() {
alert("Parentheses around the function");
})();
(function() {
alert("Parentheses around the whole thing");
}());
!function() {
alert("Bitwise NOT operator starts the expression");
}();
+function() {
alert("Unary plus starts the expression");
}();
Dans tous les cas ci-dessus, nous dĂ©clarons une fonction expression et lâexĂ©cutons immĂ©diatement. Notons encore : de nos jours il nây a aucune raison dâĂ©crire un tel code.
Résumé
Il y a deux différences majeures entre var et let/const:
- Les variables
varnâont pas de portĂ©e de bloc, leur visibilitĂ© est Ă©tendue Ă la fonction actuelle, ou globale, si elle est dĂ©clarĂ©e hors fonction. - Les dĂ©clarations
varsont traitées au début de la fonction (ou au début du script pour le cas global).
Il y a une autre diffĂ©rence mineure associĂ©e Ă lâobjet global, mais nous traiterons ce point dans le prochain chapitre.
Ces diffĂ©rences rendent var pire que let dans la plupart des cas. Les variables au niveau des blocs sont extraordinaires. Câest pourquoi let a Ă©tĂ© introduit au standard il y a longtemps et câest maintenant un moyen majeur (avec const) pour dĂ©clarer une variable.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâŠ)