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â¦)