Répertoire d'articles
Préface: Les inconvénients des variables de déclaration var dans ES5
ES5 nous fournit en fait deux méthodes de déclaration de variables: les var
commandes et les function
commandes. L'utilisation de function
commandes pour déclarer des fonctions n'est pas abordée ici, nous comparons principalement les var
commandes.
Auparavant, nous avons expliqué en détail dans l'article de mise en route de JS var
qu'il existe trois caractéristiques principales des variables de déclaration de commande:
- Les variables peuvent être déclarées à plusieurs reprises;
- Les déclarations de variables seront promues;
- Aucune portée au niveau du bloc;
Ces trois caractéristiques font que l'écriture du code JS semble un peu «aléatoire» et pas assez standardisée, et une telle logique grammaticale est également contre-intuitive. Donnez deux exemples:
- La variable interne couvrira la variable externe
avec le même nom: ci - dessous, nousvar
déclarons une variable globale etnum
attribuons une valeur de 1, puis redéclarons la variableshow
dans leif
bloc de code de la portée de la fonctionnum
et attribuons une valeur de 2:
var num = 1;
function show() {
console.log(num);
if (false) {
var num = 2;
}
}
show();
——————OUTPUT——————
undefined
Le résultat final de la show
sortie de l'exécution de la fonction est undefined
.
En effet, la var
variable déclarée n'a pas de portée au niveau du bloc et la deuxième redéclaration num
sera promue au début de la fonction, couvrant la variable globale externe du même nom. À ce stade, le résultat de sortie doit être undefined
. (Les trois caractéristiques sont reflétées dans un exemple)
- Les variables de boucle utilisées pour compter dans diverses structures de boucle seront divulguées en tant que variables globales: lorsque
nous utilisons des structures de boucle, nous déclarerons une variable de contrôle de boucle (telle que i, j, k, etc.), mais après la fin de la boucle, elle ne disparaît pas , Fuite dans une variable globale.
for (var i = 0; i < 3; i++) {
//...
}
console.log(i);
——————OUTPUT——————
2
Une meilleure approche est que nous voulons qu'il ne soit valide que dans le contrôle de boucle, et il échouera automatiquement après la fin de la boucle et n'affectera pas l'exécution des autres parties du code. À ce stade, nous devons utiliser les nouvelles let
commandes de notre ES6 .
1. Bases de Let et Const
1.1 Utilisation basique de let
let
Les commandes sont de nouvelles commandes utilisées pour déclarer des variables dans la norme ES6. Sa mission est de remplacer les var
commandes, son utilisation est similaire var
, mais elle compense var
les défauts de conception.
La différence la plus fondamentale entre les deux est que la let
commande peut déclarer le bloc de code actuel en tant que portée de niveau bloc (détaillée dans les chapitres suivants), et let
les variables déclarées par la commande ne sont valides que dans le bloc de code actuel.
(Le bloc de code est dans une paire d'accolades {}
)
{
let a = 1;
var b = 2;
}
a // ReferenceError: a is not defined.
b // 2
L'accès à la variable en dehors du bloc de code a
sera signalé une erreur non définie tout en utilisant var
des b
variables définies peut toujours être consulté.
Maintenant, avec la let
commande, vous pouvez résoudre le deuxième problème au début de cet article: le problème des fuites de variables de boucle. Nous utilisons l' instruction du for
compteur de boucle :i
let
for (let i = 0; i < 3; i++) {
//...
}
console.log(i);
——————OUTPUT——————
// ReferenceError: i is not defined
La variable i
n'est pas accessible pour le moment .
❀ Développez un peu (1) ❀
let
Il y a un autre point à noter lors de l'utilisation de commandes dans des boucles: les variables i
seront redéclarées à chaque fois dans la boucle .
Regardons d'abord l'utilisation de la var
variable de boucle déclarée i
et ajoutons une fonction de minuterie pour afficher cette variable de boucle dans chaque boucle i
:
for(var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
——————OUTPUT——————
3
3
3
Trois 3 sont émis car la variable de boucle dans toute la boucle for est i
toujours la même variable, et finalement la variable de fin de boucle i
reçoit la valeur 2. Puis passez à la let
commande et sortez-la à nouveau:
for(let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
——————OUTPUT——————
0
1
2
Vous pouvez voir que le résultat de la sortie est le même que sans la fonction de minuterie. Cela est dû au fait que la variable i
est de nouveau déclarée à chaque fois dans la boucle. La raison pour laquelle elle est sortie selon la logique normale est que le moteur JavaScript se souviendra de la valeur de la boucle précédente , Lors de l'initialisation des variables de ce tour, le i
calcul est effectué sur la base du tour précédent.
❀ Développez un peu (2) ❀
La boucle for elle-même a une autre caractéristique spéciale - la partie où la variable de boucle est définie est une portée parent, et l'intérieur du corps de la boucle est une portée enfant distincte.
for (let i = 0; i < 3; i++) {
let i = 'zevin';
console.log(i);
}
——————OUTPUT——————
zevin
zevin
zevin
Il a été produit 3 fois zevin
. Cela montre que les variables à l'intérieur du corps de la boucle i
et les variables de la boucle ne i
sont pas dans la même portée et ont leurs propres portées distinctes.
1.2 Utilisation de base de const
const
La commande est utilisée pour déclarer une constante en lecture seule. Il doit être attribué au début de la déclaration et ne peut pas être modifié une fois déclaré.
const PI;
// SyntaxError: Missing initializer in const declaration
const PI = 3.1415926;
PI = 3.14;
// TypeError: Assignment to constant variable.
❀ Développez-le ❀
L'essence de la commande const
Ce que la commande const garantit en fait n'est pas que la valeur de la variable ne peut pas être modifiée, mais que les données stockées dans l'adresse mémoire pointée par la variable ne peuvent pas être modifiées.
Pour les types de base de données simples (valeur numérique, chaîne, valeur booléenne), l'adresse mémoire pointée par la variable stocke la valeur elle-même, elle équivaut donc à la valeur de la variable qui ne peut pas être modifiée;
const obj = {
};
// 可以添加属性
obj.name = 'zevin';
console.log(obj.name);
// zevin
// 让obj指向另一个对象就会报错
foo = {
};
// TypeError: "obj" is read-only
Pour les types de données de référence (principalement des tableaux, des objets), l'adresse mémoire pointée par la variable enregistre l'adresse de référence, mais l'adresse de référence ne peut pas être modifiée. Pour le tableau, l'objet lui-même, nous pouvons toujours ajouter ou supprimer élément.
2. Nouvelle spécification de déclaration de variable ES6
Afin d'améliorer la situation dans une instruction ES5 var commande, mais aussi afin d'améliorer le langage normatif JS, ES6 propose les quatre nouvelles normes de déclaration de variables suivantes, let
et les const
commandes sont applicables.
2.1 Portée au niveau du bloc
ES5 n'a qu'une portée globale et une portée fonctionnelle.Enfin, la portée au niveau bloc a été ajoutée à ES6. Utilisez let
ou la const
variable de commande d'action de niveau bloc déclarée dans une instruction uniquement lorsque le domaine est valide.
{
let a = 1;
if(true){
const a = 2;
};
console.log(a);
}
——————OUTPUT——————
1
Le bloc de code est basé sur une paire d'accolades {}
, qui peuvent être imbriquées arbitrairement sans affecter l'autre.
{
{
{
{
{
const name = 'zevin' }
console.log(name);
// 报错
}}}};
Le code ci-dessus utilise une portée de niveau bloc à cinq niveaux, chacune étant une portée distincte. La portée de quatrième niveau ne peut pas lire les variables internes de la portée de cinquième niveau.
2.2 Il n'y a pas de promotion variable
var
La variable déclarée par la commande sera promue au début du document ou au début de la fonction, c'est-à-dire que la variable peut être utilisée avant la déclaration, et la valeur est undefined
. Et corrigé la grammaire dans le comportement ES6, let
et la const
commande variable doit être déclarée dans une instruction après utilisation, sinon une erreur.
console.log(a);
console.log(b);
console.log(c);
var a = 1;
let b = 2;
const c = 3;
——————OUTPUT——————
undefined
ReferenceError: Cannot access 'b' before initialization
ReferenceError: Cannot access 'c' before initialization
2.3 Zone morte temporaire
ES6 clair que, si le bloc existe let
et const
commande, ce bloc ces commandes déclarations de variables, dès le départ pour former une portée fermée. Si ces variables sont utilisées avant la déclaration, une erreur sera signalée. Ceci est grammaticalement appelé "zone morte temporelle" (TDZ pour faire court).
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
Dans le code ci-dessus, avant que la let
commande déclare la variable tmp
, tous appartiennent à tmp
la "zone morte" de la variable .
❀ Développez-le ❀
L'émergence d'une «zone morte temporaire» signifie également que ce typeof
n'est plus une opération qui ne rapportera jamais d'erreurs.
typeof a; // undefined
typeof b; // ReferenceError
const b = 1;
L' b
utilisation des variables const
avant de déclarer les variables appartient à b
la "zone morte", tant que l'utilisation de cette variable est une erreur. Par conséquent, l' typeof
opérateur lancera une ReferenceError
erreur.
Mais si une variable n'est pas du tout déclarée (variable a
), typeof
elle ne signalera pas d'erreur lorsqu'elle est utilisée undefined
.
2.4 Les déclarations en double ne sont pas autorisées
ES6 n'autorise pas les déclarations multiples de la même variable dans la même portée.
if(true){
var a = 1;
let a = 2;
const a = 3;
}
// SyntaxError: Identifier 'a' has already been declared
Par conséquent, de la même manière, la variable portant le même nom que le paramètre formel ne peut pas être utilisée let
ou const
commandée dans la fonction , mais elle le var
peut.
function func(num) {
let num = 1;
console.log(num);
}
func()
// SyntaxError: Identifier 'num' has already been declared
function func(num) {
var num = 1;
console.log(num);
}
func()
// 1
Étant donné que différentes étendues de niveau bloc ne s'affectent pas, nous pouvons définir des variables avec le même nom dans différentes étendues de niveau bloc. Ainsi, le code suivant ne signalera pas d'erreur:
function func(num) {
var num = 1;
if(true){
let num = 2;
}else{
const num =3;
}
}
func()
3. Extension: six façons de déclarer des variables dans ES6
ES5 | ES6 |
---|---|
fonction var |
let const importer la classe |
ES6 en fait, quatre nouvelles méthodes de déclaration de variable: Cet article présente les let
commandes et la const
commande, suivi-introduit à nouveau les import
commandes et la class
commande. Couplé aux var
commandes et function
commandes dans ES5 , il existe six façons de déclarer des variables dans ES6.