Comprendres les variables et constantes en JavaScript (ES6) - var, let, const
Tags: javascript, francais, es6
Published: 2022-01-24 17:49:59

Le JavaScript à l'ancienne avait un problème. Entre le hissage(hoisting) et les déclarations de variables ambiguës, la gestion des données dans votre code peut être un vrai cauchemard en JS.
Heureusement, depuis l'arrivée d'ES6, nous avons de nouvelles façons de nous assurer que nos variables et nos constantes sont gérées correctement.
Voyons comment cela fonctionne, et nettoyons notre code.

## Variables non déclarées - à éviter !

Le premier problème est que si nous créons une variable sans la déclarer, elle est définie comme une variable globale par défaut.
Voici un exemple avec deux fonctions :
```javascript
function declareVar() {
  test = "test";
}

function declareVar2() {
  test = "test 2";
}

declareVar();
console.log(test);// Renvoie "test"

declareVar2();
console.log(test);// Renvoie "test 2"

```

Nous venons de créer une variable  `test`, qui est visible globalement, en dehors de la fonction `declareVar()`.
`declareVar2()` modifiera la même variable ... ce n'est pas nécessairement ce qui était prévu.

On peut forcer la déclaration explicite des variables en utilisant le mode JS strict :

```javascript
`use strict`;
test = "test";
```

Ce code renverra une erreur, pour nous protéger de nous-même:

	`ReferenceError: num is not defined`

Mais même si on créé nos variables explicitement, il y a d'autres problèmes.

## `var` - définitions de variables ambiguës

Deuxième problème: même si nous déclarons correctement une variable en utilisant `var`, il est toujours possible de redéclarer la même variable plus tard. 
Dans ces conditions, difficile de conserver des noms et des définitions cohérents pour vos variables, et donc de débugger votre programme:
```javascript
var num = 100;
// du code, et du code, et du code...
var num = 200;
```

Regardons le code ci-dessus. Est-ce que nous attribuons une nouvelle valeur à une variable pré-existante(mais alors, pourquoi la redéclarer ensuite?), ou est-ce que nous déclarons une nouvelle variable avec le même nom (deux variables avec le même nom? Désastre guaranti). Les deux options sont mauvaises.

La portée(scope) des variables est également un problème. Cela peut prêter à confusion si nous créons une variable dans un bloc ; la variable commencera à "déborder" du bloc :

```javascript
console.log(msg);// On peut voir cette variable en dehors du bloc
for(var i = 0; i < 3; i++) {
	var msg = "Hellow world";
}
```

À cause du hoisting,  `msg`, qui est déclaré à l'intérieur de la boucle `for`, sera visible à l'extérieur de la boucle, avant même d'être déclarée. Ce n'est pas idéal non plus.  
Voyons les alternatives que ES6 nous offre pour résoudre ces problèmes.

## Alternatives supérieures:  `const` et `let`

### `let`, une façon plus efficace de déclarer des variables

Pour commencer, en déclarant une variable avec `let`, vous ne pouvez pas redéclarer la même variable dans le même scope:

```javascript
let num = 100;
// Some other code...
let num = 200;
```

Nous renverra:

	SyntaxError: Identifier 'num' has already been declared

Les variables déclarées avec `let` ont également un **scope de bloc**. Scope de bloc signifie que les variables ne seront pas disponibles en dehors des blocs de code dans lesquels elles ont été déclarées (entre les accolades `{` et `}`).
Ce code :
```javascript
for(var i = 0; i < 3; i++) {
  let msg2 = "Hellow world";
}
console.log(msg2);
```

Ne fonctionnera pas et lancera une erreur `ReferenceError: msg2 is not defined`, car `msg2` n'est accessible qu'à l'intérieur de la boucle `for`.

De plus, la variable n'est pas disponible tant qu'elle n'est pas déclarée :

```javascript
for(var i = 0; i < 3; i++) {
  console.log(msg2);
  let msg2 = "Hellow world";
}
```

Enverra également une erreur `ReferenceError` (`Cannot access 'msg2' before initialization`) : `msg2` n'est pas encore entièrement initialisé.

Par conséquent, nous devons utiliser une approche plus logique, où nous ne pouvons accèder à la variable qu'*après*  sa déclaration, dans son propre bloc :

```javascript
for(var i = 0; i < 3; i++) {
	let msg2 = "Hellow world";
	console.log(msg2);
}
```

Propre, facile à lire, cleaner, easier to read, non ambigu. Et boum!

### `const` - pour les variables qui ne devraient pas changer

Parfois, vous devez vous assurer que la valeur de vos variables ne change pas ; elle doit être *immuable*.
Pour cela, utilisez `const` au lieu de `let`. En fait, utilisez `const` par défaut, sauf si vous devez déclarer une variable qui *doit* absolument changer de valeur au cours du cycle de vie de votre programme.

**Attention cependant**, si votre constante est une référence à un objet, vous *pourrez* changer les *propriétés* de l'objet, comme ci-dessous :

```javascript
const client = {name:"John", "number":234};
client.name = "Sue"; // client.name a été modifié
```

Pour rendre une référence d'objet immuable, utilisez la méthode "Object.freeze" :

```javascript
const client = Object.freeze({name:"John", "number":234});
client.name = "Sue"; // ceci n'aura aucun effet
console.log(client); // renverra toujours {name: "John", number: 234}
```

Cela ne fonctionne qu'au premier niveau ; si les propriétés de votre objet sont des références à d'autres objets, vous devrez utiliser `Object.freeze` sur chacun d'eux.

Et voilà, c'est ainsi que vous déclarez les variables proprement en ES6+.
Faites-moi savoir comment vous aimez gérer vos variables en JS dans les commentaires.