Const en JavaScript: quand l'utiliser et est-ce nécessaire?

349

J'ai récemment rencontré le constmot - clé en JavaScript. D'après ce que je peux dire, il est utilisé pour créer des variables immuables , et j'ai testé pour m'assurer qu'il ne peut pas être redéfini (dans Node.js):

const x = 'const';
const x = 'not-const';

// Will give an error: 'constant 'x' has already been defined'

Je me rends compte qu'il n'est pas encore standardisé sur tous les navigateurs - mais je ne suis intéressé que par le contexte de Node.js V8 , et j'ai remarqué que certains développeurs / projets semblent le favoriser fortement lorsque le varmot - clé pourrait être utilisé pour le même effet.

Mes questions sont donc:

  • Quand est-il approprié d'utiliser constà la place de var?
  • Doit-elle être utilisée chaque fois qu'une variable qui ne va pas être réaffectée est déclarée?
  • Cela fait-il réellement une différence s'il varest utilisé à la place constou vice-versa?
axdg
la source
1
Cela ne semble pas encore standardisé (peut-être en EC6?). Vous trouverez des informations supplémentaires à ce sujet ici: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Sebastien C.
1
Const a de mauvaises performances si jsperf.com/const-vs-var-mod-3
Deepu

Réponses:

462

Il y a deux aspects à vos questions: quels sont les aspects techniques de l'utilisation constau lieu de varet quels sont les aspects liés à l'homme de le faire.

La différence technique est importante. Dans les langages compilés, une constante sera remplacée au moment de la compilation et son utilisation permettra d'autres optimisations comme la suppression de code mort pour augmenter encore l'efficacité d'exécution du code. Les moteurs JavaScript récents (terme peu utilisé) compilent en fait du code JS pour obtenir de meilleures performances, donc l'utilisation du mot-clé const les informerait que les optimisations décrites ci-dessus sont possibles et devraient être faites. Il en résulte de meilleures performances.

L'aspect humain concerne la sémantique du mot-clé. Une variable est une structure de données qui contient des informations qui devraient changer. Une constante est une structure de données qui contient des informations qui ne changeront jamais. S'il y a place à l'erreur, vardoit toujours être utilisé. Cependant, toutes les informations qui ne changent jamais dans la durée de vie d'un programme n'ont pas besoin d'être déclarées avec const. Si, dans des circonstances différentes, les informations doivent changer, utilisez varpour indiquer que, même si la modification réelle n'apparaît pas dans votre code.

Tibos
la source
4
À la vôtre, j'ai supposé que Mozilla / Google n'aurait pas ajouté le support const aux moteurs JS sans aucune raison. Je m'assurerai d'utiliser const le cas échéant.
axdg
6
constles objets semblent être mutables, donc je ne sais pas à quel point le compilateur JS est strict. Peut-être que le mode "utiliser strict" fait aussi une différence.
Rudie
9
@Rudie La fonctionnalité que vous recherchez s'appelle geler l'objet. constempêche simplement de réaffecter la "variable" à une autre valeur. const a = {}; a = {};va lancer une erreur en mode strict.
Tibos
J'utilise const en général au lieu de let pour la plupart des variables, tout comme en Java j'ajoute final à la plupart des déclarations de variables.
codage
2
If there is room for error, var should always be used. Aujourd'hui, cela ne s'applique plus, avec des outils comme ESLint pointant constimmédiatement la violation.
vitaly-t
72

Mise à jour 2017

Cette réponse reçoit toujours beaucoup d'attention. Il convient de noter que cette réponse a été publiée début 2014 et que beaucoup de choses ont changé depuis.le soutien est désormais la norme. Tous les navigateurs modernes prennent désormais en charge const, il devrait donc être assez sûr à utiliser sans aucun problème.


Réponse originale de 2014

Malgré une prise en charge du navigateur assez décente , j'éviterais de l'utiliser pour l'instant. Extrait de l'article de MDN surconst :

L'implémentation actuelle de const est une extension spécifique à Mozilla et ne fait pas partie d'ECMAScript 5. Elle est prise en charge dans Firefox et Chrome (V8). Depuis Safari 5.1.7 et Opera 12.00, si vous définissez une variable avec const dans ces navigateurs, vous pouvez toujours changer sa valeur plus tard. Elle n'est pas prise en charge dans Internet Explorer 6-10, mais est incluse dans Internet Explorer 11. Le mot clé const déclare actuellement la constante dans la portée de la fonction (comme les variables déclarées avec var).

Il poursuit en disant:

constva être défini par ECMAScript 6, mais avec une sémantique différente. Comme pour les variables déclarées avec l'instruction let, les constantes déclarées avec const auront une portée de bloc.

Si vous utilisez, constvous devrez ajouter une solution de contournement pour prendre en charge les navigateurs légèrement plus anciens.

James Donnelly
la source
6
Excellente réponse - même si j'ai déjà lu l'article sur MDN. Comme je l'ai dit, j'étais plus intéressé à savoir si V8 spécifiquement allait réellement traiter const différemment de var. Je pense que @Tibos a clarifié cela.
axdg
James remercie d'avoir souligné l'aspect du support. à mon humble avis, toutes les réponses javascript doivent inclure une ventilation du support du navigateur. bien expliqué
hubson bropa
4
Remarque ES6 a reçu un gel des fonctionnalités en août 2014. En juillet 2015, la norme a été officiellement publiée. Si vous lisez ceci maintenant, cela signifie que vous devez suivre la réponse acceptée comme indiqué si votre code est géré par un moteur à jour.
Filip Dupanović
La question OP est spécifique à node.js
Nicu Surdu
@NicolaeSurdu bien sûr. C'est aussi à partir de janvier 2014, donc c'est probablement surtout redondant maintenant en 2017.
James Donnelly
41

Pour savoir pourquoi utiliser const, la réponse de @ Tibos est excellente.

Mais vous avez dit:

D'après ce que je peux dire, il est utilisé pour créer des variables immuables

C'est faux . La mutation d'une variable est différente de la réaffectation:

var hello = 'world' // assigning
hello = 'bonjour!' // reassigning

Avec const, vous ne pouvez pas faire ça:

const hello = 'world'
hello = 'bonjour!' // error

Mais vous pouvez muter votre variable:

const marks = [92, 83]
marks.push(95)
console.log(marks) // [92, 83, 95] -> the variable has been mutated.

Ainsi, tout processus qui modifie la valeur de la variable sans utiliser le =signe mute la variable.

Remarque: +=par exemple, c'est ... une nouvelle affectation!

var a = 5
a += 2 // is the same as a = a + 2

Donc, l'essentiel est: constne vous empêche pas de muter les variables, il vous empêche de les réaffecter .

math2001
la source
4
votre déclaration "tout processus qui modifie la valeur de la variable sans utiliser le =signe est en sourdine" est techniquement erronée. Par exemple, const marks=[92,83]; marks[2]=95; console.log(marks)sortira [92, 83, 95]. marksa été muté, via un signe égal.
chharvey
5
"Mais vous avez dit: << D'après ce que je peux dire, il est utilisé pour créer des variables immuables >> C'est faux . La mutation d'une variable est différente de la réaffectation" Non, ce n'est pas le cas. La réaffectation entraîne la mutation de la variable. Vous parlez de muter l'objet auquel la référence dans la variable fait référence. C'est une tout autre chose.
TJ Crowder
Je suis arrivé ici parce que j'essaie de comprendre constdans le contexte des tableaux (similaire à l'exemple utilisé par @chharvey). Dans le cas de const countArray = countup(n - 1); countArray.push(n);l' constest réaffecté à chaque fois. Alors pourquoi l'utiliser constet non var?
YCode
1
@YCode no. lorsque vous utilisez const countArray, il ne sera jamais réaffecté. Vous pouvez toujours pousser vers le tableau, qui change ses membres et sa longueur, mais nous n'appelons pas cela une réaffectation. vous utilisez à la constplace de letou varlorsque vous souhaitez empêcher la réaffectation. BTW si vous ne voulez autoriser réattribution, letest presque toujours mieux que var.
chharvey
@chharvey Merci! Votre réponse m'a amené à «passer par valeur vs passer par référence», un nouveau concept, et un étrange - où la modification de valeur ≠ la réaffectation. Toute personne ayant besoin d'explications supplémentaires doit vérifier les réponses ici: stackoverflow.com/q/46131828/5965865
YCode
38

Pour intégrer les réponses précédentes, il y a un avantage évident à déclarer des variables constantes, en dehors de la raison des performances: si vous essayez accidentellement de les modifier ou de les déclarer à nouveau dans le code, le programme ne modifiera pas respectivement la valeur ou ne générera pas d'erreur.

Par exemple, comparez:

// Will output 'SECRET'

const x = 'SECRET'
if (x = 'ANOTHER_SECRET') {  // Warning! assigning a value variable in an if condition
    console.log (x)
}

avec:

// Will output 'ANOTHER_SECRET'

var y = 'SECRET'
if (y = 'ANOTHER_SECRET') { 
    console.log (y)
}

ou

// Will throw TypeError: const 'x' has already been declared

const x = "SECRET"

/*  complex code */

var x = 0

avec

// Will reassign y and cause trouble

var y = "SECRET"

/*  complex code */

var y = 0
janesconference
la source
Vous devez dire que ce comportement "immuable" ne s'applique qu'aux chaînes, types de base. En utilisant des objets, des tableaux, etc., il est possible de modifier les valeurs, mais il n'est pas possible de réaffecter un nouvel "objet", par exemple const a = ["a", "b"]; a = []; va lancer une erreur sinon il est possible
Fer To
Vous devriez avoir un exemple où vous essayez de changer la valeur d'une constante également.
Joshua Pinter
L'utilisation de const est très similaire aux modificateurs d'accès, la véritable immuabilité n'est pas le but.
StingyJack
32

constn'est pas immuable.

Du MDN :

La déclaration const crée une référence en lecture seule à une valeur. Cela ne signifie pas que la valeur qu'il contient est immuable, mais simplement que l'identificateur de variable ne peut pas être réaffecté.

Anthony
la source
24
C'est un peu trompeur cependant. Pour les nombres, les chaînes, les booléens, etc. (primitives) constest immuable. Pour les objets et les tableaux, il ne peut pas être réaffecté, mais le contenu peut être modifié (par exemple array.push).
Florian Wendelborn du
2
Les primitives JS sont cependant toujours immuables. Que vous l'utilisiez constou non n'affecte pas cela.
12Me21
1
@Dodekeract n'est donc pas immuable par définition. Si les valeurs peuvent changer, elle n'est pas immuable, bien qu'elle fonctionne comme immuable pour les primitives que vous avez répertoriées
Anthony
13

var : déclarer une variable, initialisation de la valeur facultative.

laisser : Déclarez une variable locale avec une portée de bloc.

const : déclare une constante nommée en lecture seule.

Ex:

var a;
a = 1;
a = 2;//re-initialize possible
var a = 3;//re-declare
console.log(a);//3

let b;
b = 5;
b = 6;//re-initiliaze possible
// let b = 7; //re-declare not possible
console.log(b);

// const c;
// c = 9;   //initialization and declaration at same place
const c = 9;
// const c = 9;// re-declare and initialization is not possible
console.log(c);//9
// NOTE: Constants can be declared with uppercase or lowercase, but a common
// convention is to use all-uppercase letters.
Srikrushna
la source
10

Vous avez d'excellentes réponses, mais restons simples.

const doit être utilisé lorsque vous avez une constante définie (lire: elle ne changera pas pendant l'exécution de votre programme).

Par exemple:

const pi = 3.1415926535

Si vous pensez que c'est quelque chose qui peut être modifié lors d'une exécution ultérieure, utilisez un var .

La différence pratique, basée sur l'exemple, est qu'avec const vous supposerez toujours que pi sera 3,14 [...], c'est un fait.

Si vous le définissez comme var , il peut être 3,14 [...] ou non.

Pour une réponse plus technique, @Tibos a tout à fait raison.

Edgar Griñant
la source
7

D'après mon expérience, j'utilise const lorsque je veux définir quelque chose que je pourrais vouloir changer plus tard sans avoir à parcourir le code à la recherche de bits qui ont été codés en dur, par exemple un chemin de fichier ou un nom de serveur.

L'erreur dans vos tests est une autre chose cependant, vous essayez de créer une autre variable appelée x, ce serait un test plus précis.

const x = 'const';
x = 'not-const';
Funkotron_King
la source
9
Je comprends ce que vous voulez dire, mais - c'est drôle que «constant» pour vous signifie «chose que je pourrais vouloir changer». : P
Venryx
4

Préférence personnelle vraiment. Vous pouvez utiliser const lorsque, comme vous le dites, il ne sera pas réaffecté et est constant. Par exemple, si vous souhaitez attribuer votre anniversaire. Votre anniversaire ne change jamais, vous pouvez donc l'utiliser comme une constante. Mais votre âge change, ce qui pourrait être une variable.

Carl Markham
la source
17
Ce serait un script très long!
nullabilité
3
@nullability Dépend du nombre de personnes que vous suivez. Plus de quelques dizaines et le script n'aura pas à s'exécuter longtemps :).
Millie Smith
4

Sommaire:

const crée une liaison immuable, ce qui signifie que l'identificateur de variable const n'est pas réaffectable.

const a = "value1";

vous ne pouvez pas le réaffecter avec

a = "value2";

Cependant, si l'identifiant const contient un objet ou un tableau, sa valeur peut être modifiée dans la mesure où nous ne le réaffectons pas.

const x = { a: 1 }

x.a = 2; //is possible and allowed

const numbers = [1, 2];
numbers.push(3); //is possible and allowed

Veuillez noter que const est un bloc de portée tout comme let qui n'est pas identique à var (qui est de portée fonction)

En bref, quand quelque chose n'est pas susceptible de changer par la réaffectation, utilisez const sinon utilisez let ou var selon l'étendue que vous souhaitez avoir.

Il est beaucoup plus facile de raisonner sur le code lorsqu'il est évident de savoir ce qui peut être changé par la réaffectation et ce qui ne peut pas l'être. Changer un const en let est très simple. Et aller const par défaut vous fait réfléchir à deux fois avant de le faire. Et c'est dans de nombreux cas une bonne chose.

Tejas Patel
la source
2
Main point is that how to decide which one identifier should be used during development.
In java-script here are three identifiers.

1. var (Can re-declared & re-initialize)
2. const (Can't re-declared & re-initialize, can update array values by using push)
3. let (Can re-initialize but can't re-declare)

'var': Au moment du codage, lorsque nous parlons de code standard, nous utilisons généralement le nom de l'identifiant, facile à comprendre par les autres utilisateurs / développeurs. Par exemple, si nous travaillons sur de nombreuses fonctions où nous utilisons des entrées et les traitons et retournons des résultats, comme:

**Example of variable use**

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2;
 return result;
}

Dans les exemples ci-dessus, les deux fonctions produisent des résultats différents de 2 mais utilisent le même nom de variables. Ici, nous pouvons voir que «processus» et «résultat» sont tous deux utilisés comme variables et ils devraient l'être.

 **Example of constant with variable**

 const tax = 10; 
 const pi = 3.1415926535; 

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

Avant d'utiliser 'let' dans java-script, nous devons ajouter 'use strict' en haut du fichier js

 **Example of let with constant & variable**

 const tax = 10; 
 const pi = 3.1415926535; 
 let trackExecution = '';

function firstFunction(input1,input2)
{
 trackExecution += 'On firstFunction'; 
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 trackExecution += 'On otherFunction'; # can add current time 
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

 firstFunction();
 otherFunction();
 console.log(trackExecution);

Dans l'exemple ci-dessus, vous pouvez suivre la fonction exécutée et la fonction non utilisée lors d'une action spécifique.

vinod
la source
1

Tout d'abord, trois choses utiles const(à part les améliorations de portée avec lesquelles il partage let):

  • Il indique aux personnes lisant le code ultérieurement que la valeur ne doit pas changer.
  • Cela vous empêche (ou quiconque vient après vous) de modifier la valeur à moins qu'ils ne reviennent en arrière et ne modifient intentionnellement la déclaration.
  • Cela pourrait sauver le moteur JavaScript d'une analyse en termes d'optimisation. Par exemple, vous avez déclaré que la valeur ne peut pas changer, donc le moteur n'a pas à faire de travail pour déterminer si la valeur change afin qu'il puisse décider s'il faut optimiser en fonction de la valeur qui ne change pas.

Vos questions:

Quand est-il approprié d'utiliser constà la place de var?

Vous pouvez le faire à chaque fois que vous déclarez une variable dont la valeur ne change jamais. Que vous jugiez approprié ou non, cela dépend entièrement de vos préférences / de celles de votre équipe.

Doit-elle être utilisée chaque fois qu'une variable qui ne va pas être réaffectée est déclarée?

Cela dépend de vous / de votre équipe.

Cela fait-il vraiment une différence si var is used in place ofconst` ou vice-versa?

Oui:

  • varet constont des règles de portée différentes. (Vous auriez peut-être voulu comparer avec letplutôt qu'avec var.) Spécifiquement: constet letont une portée de bloc et, lorsqu'ils sont utilisés à portée globale, ne créent pas de propriétés sur l'objet global (même s'ils créent des globaux). vara une portée globale (lorsqu'elle est utilisée à la portée globale) ou une portée de fonction (même si elle est utilisée dans un bloc), et lorsqu'elle est utilisée à la portée globale, crée une propriété sur l'objet global.
  • Voir mes "trois choses utiles" ci-dessus, elles s'appliquent toutes à cette question.
TJ Crowder
la source
1

La sémantique de varetlet

varet letsont une déclaration à la machine et aux autres programmeurs:

J'ai l'intention que la valeur de cette affectation change au cours de l'exécution. Ne vous fiez pas à la valeur éventuelle de cette mission.

Implications de l'utilisation varetlet

varet letforcer les autres programmeurs à lire tout le code intermédiaire de la déclaration à l'utilisation finale, et à raisonner sur la valeur de l'affectation à ce stade de l'exécution du programme.

Ils affaiblissent le raisonnement de la machine pour qu'ESLint et d'autres services de langage détectent correctement les noms de variables mal typés dans les affectations ultérieures et la réutilisation de la portée des noms de variables de la portée externe où la portée interne oublie de déclarer.

Ils entraînent également l'exécution de nombreuses itérations sur tous les chemins de code pour détecter qu'elles sont en fait des constantes avant de pouvoir les optimiser. Bien que ce soit moins un problème que la détection de bogues et la compréhensibilité des développeurs.

Quand utiliser const

Si la valeur de la référence ne change pas au cours de l'exécution, la syntaxe correcte pour exprimer l'intention du programmeur est const. Pour les objets, changer la valeur de la référence signifie pointer vers un autre objet, car la référence est immuable, mais l'objet ne l'est pas.

" const" objets

Pour les références d'objet, le pointeur ne peut pas être changé en un autre objet, mais l'objet qui est créé et affecté à une constdéclaration est modifiable. Vous pouvez ajouter ou supprimer des éléments d'un consttableau référencé et muter les clés de propriété sur un constobjet référencé.

Pour réaliser des objets immuables (ce qui, encore une fois, rend votre code plus facile à raisonner pour les humains et les machines), vous pouvez Object.freezel'objet à la déclaration / affectation / création, comme ceci:

const Options = Object.freeze(['YES', 'NO'])

Object.freeze a un impact sur les performances, mais votre code est probablement lent pour d'autres raisons. Vous voulez le profiler.

Vous pouvez également encapsuler l'objet modifiable dans une machine à états et renvoyer des copies complètes sous forme de valeurs (c'est ainsi que fonctionnent les états Redux et React). Voir Éviter un état global mutable dans Browser JS pour un exemple de la façon de construire cela à partir des premiers principes.

Quand varet letsont un bon match

letet varreprésentent un état mutable. Ils ne devraient, à mon avis, être utilisés que pour modéliser un état mutable réel . Des choses comme " la connexion est-elle vivante? ".

Celles-ci sont mieux encapsulées dans des machines à états testables qui exposent des valeurs constantes qui représentent " l'état actuel de la connexion ", qui est une constante à tout moment, et ce qui intéresse réellement le reste de votre code.

La programmation est déjà assez difficile avec la composition des effets secondaires et la transformation des données. Transformer chaque fonction en une machine à états non testable en créant un état mutable avec des variables ne fait qu'accroître la complexité.

Pour une explication plus nuancée, voir Shun the Mutant - The case forconst .

Josh Wulf
la source
0

Je ne suis pas un expert dans le domaine de la compilation JS, mais il est logique de dire que la v8 utilise le drapeau const

Normalement, après avoir déclaré et modifié un tas de variables, la mémoire est fragmentée et la v8 s'arrête pour s'exécuter, fait une pause de quelques secondes, pour faire gc ou garbage collection.

si une variable est déclarée avec const v8, vous pouvez être sûr de la placer dans un conteneur de taille fixe étanche entre les autres variables const, car elle ne changera jamais. Il peut également enregistrer les opérations appropriées pour ces types de données, car le type ne changera pas.

Juif
la source
0

En ce qui concerne la décision entre let et const , préférez toujours const pour que l'utilisation soit claire dans le code. De cette façon, si vous essayez de redéclarer la variable, vous obtiendrez une erreur. S'il n'y a pas d'autre choix que de le redéclarer, il suffit de changer pour laisser . Notez que, comme le dit Anthony , les valeurs ne sont pas immuables (par exemple, un objet const peut avoir des propriétés mutées).

En ce qui concerne var , puisque ES6 est sorti, je ne l'ai jamais utilisé dans le code de production et je ne peux pas penser à un cas d'utilisation pour cela. Mais attention, les variables déclarées avec var n'ont pas de portée de bloc.

Tiago Martins Peres 李大仁
la source