web-dev-qa-db-fra.com

Pourquoi puis-je changer la valeur d'une constante en javascript

Je sais que ES6 n'est pas encore normalisé, mais beaucoup de navigateurs supportent actuellement le mot cléconst dans JS.

Dans spec, il est écrit que:

La valeur d'une constante ne peut pas changer lors d'une réaffectation, et un constante ne peut pas être déclarée à nouveau. Pour cette raison, bien que ce soit possible de déclarer une constante sans l'initialiser, ce serait inutile de le faire.

et quand je fais quelque chose comme ça:

const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];

Je vois que tout va bien xxx est toujours 6 et yyy est [].

Mais si je fais yyy.Push(6); yyy.Push(1);, mon tableau constant a été changé. À l’heure actuelle, c’est [6, 1] et d’ailleurs, je ne peux toujours pas le changer avec yyy = 1;.

Je présente un bogue ou est-ce que je manque quelque chose? Je l'ai essayé dans le dernier chrome et FF29

50
Salvador Dali

La documentation indique:

... constante ne peut pas changer par réaffectation
... constante ne peut pas être re-déclarée

Lorsque vous ajoutez des éléments à un tableau ou à un objet, vous ne réassignez ni ne déclarez pas la constante, elle est déjà déclarée et affectée. Vous ajoutez simplement à la "liste" pointée par la constante.

Donc ça marche bien

const x = {};

x.foo = 'bar';

console.log(x); // {foo : 'bar'}

et ça

const y = [];

y.Push('foo');

console.log(y); // ['foo'];

mais ni l'un ni l'autre

const x = {};
x = {foo: 'bar'}; // error - re-assigning

const y = ['foo'];
const y = ['bar']; // error - re-declaring

const foo = 'bar'; 
foo = 'bar2';       // error - can not re-assign
var foo = 'bar3';   // error - already declared
function foo() {};  // error - already declared
87
adeneo

Cela se produit parce que votre constante stocke en fait un reference dans le tableau. Lorsque vous joignez quelque chose à votre tableau, vous ne modifiez pas votre valeur constante, mais le tableau sur lequel il pointe. La même chose se produirait si vous affectiez un objet à une constante et tentiez de modifier ses propriétés.

Si vous voulez figer un tableau ou un objet afin qu'il ne puisse pas être modifié, vous pouvez utiliser la méthode Object.freeze , qui fait déjà partie de ECMAScript 5.

const x = Object.freeze(['a'])
x.Push('b')
console.log(x) // ["a"]
21
Guilherme Sehn

Ce comportement est cohérent avec tous les langages de programmation auxquels je peux penser.

Considérez C - les tableaux ne sont que des pointeurs glorifiés. Un tableau constant signifie uniquement que la valeur du pointeur ne changera pas - mais en réalité, les données contenues à cette adresse sont libres de.

En javascript, vous êtes autorisé à appeler des méthodes d'objets constants (bien sûr, sinon les objets constants n'auraient pas beaucoup de sens!). Ces méthodes peuvent avoir pour effet secondaire de modifier l'objet. Les tableaux en javascript étant des objets, ce comportement leur est également applicable.

Tout ce dont vous êtes assuré, c'est que la constante pointe toujours vers le même objet. Les propriétés de l'objet lui-même sont libres de changer. 

5
thorsday

La déclaration const crée une référence en lecture seule à une valeur. Cela ne signifie pas que la valeur qu'il détient est immuable, mais simplement que l'identificateur de variable ne peut pas être réaffecté. Par exemple, dans le cas où le contenu est un objet, cela signifie que le contenu de l'objet (ses paramètres, par exemple) peut être modifié.

En outre, une note également importante:

Les constantes globales ne deviennent pas des propriétés de l'objet window ...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

1
Benjamin West

Entré dans cet article en cherchant pourquoi je suis capable de mettre à jour un objet même après l'avoir défini comme const. Le point ici est que ce ne sont pas les objets directement mais les attributs qu’il contient qui peuvent être mis à jour.

Par exemple, mon objet ressemble à:

const number = {
    id:5,
    name:'Bob'
};

Les réponses ci-dessus ont correctement indiqué que c'est l'objet qui est const et non son attribut. Par conséquent, je pourrai mettre à jour l'identifiant ou le nom en faisant:

number.name = 'John';

Mais, je ne pourrai pas mettre à jour l'objet lui-même comme:

number = {
    id:5,
    name:'John'
  };

TypeError: Assignment to constant variable.
0
Atul O Holic

Je pense que cela vous éclairerait davantage sur le problème: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .

En gros, cela revient à la const qui pointe toujours vers la même adresse en mémoire. Vous pouvez modifier la valeur stockée dans cette adresse, mais vous ne pouvez pas modifier l'adresse indiquée par la variable const

La définition de const que vous avez mentionnée est vraie lorsque la const pointe vers une adresse contenant une valeur primitive. En effet, vous ne pouvez pas affecter de valeur à cette const sans modifier son adresse (car c’est ainsi que l’affectation de valeurs primitives fonctionne) et la modification de l’adresse d’une const n’est pas autorisée.

Là où, comme si la const pointe vers une valeur non primitive, il est possible de modifier la valeur de l'adresse. 

0
Zyxmn