ecmascript 6 - De ce pot să schimb un obiect constant în JavaScript?
Știu că ES6 nu este standardizat încă, dar multe browsere suportă în prezent cuvântul cheie const în JS.
În specificație, este scris că:
Valoarea unei constante nu se poate schimba prin reatribuire, iar o constantă nu poate fi redeclarată. Din această cauză, deși este posibil să declari o constantă fără a o inițializa, ar fi inutil să faci acest lucru.
și când fac ceva de genul acesta:
const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
Văd că totul este în regulă: xxx este încă 6 și yyy este [].
Dar dacă fac yyy.push(6); yyy.push(1); , array-ul meu constant a fost schimbat. În acest moment este [6, 1] și, apropo, tot nu pot să-l schimb cu yyy=1;.
Este acesta un bug, sau îmi scapă ceva? Am încercat în cea mai recentă versiune de Chrome și FF29
Răspuns #1
Documentația MDN afirmă:
...constanta nu poate fi schimbată prin re-alocare
...constanta nu poate fi redeclarată
Când adaugi ceva într-un array sau obiect, nu reatribui sau redeclari constanta; ea este deja declarată și atribuită. Pur și simplu adaugi la lista de elemente sau proprietăți la care constantul face referire.
Deci asta funcționează bine:
const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
și asta:
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']
dar nici unul dintre acestea:
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
Răspunsul #2
Acest lucru se întâmplă deoarece constanta ta stochează de fapt o referință către array. Când adaugi ceva în array-ul tău, nu modifici valoarea constantei, ci array-ul la care aceasta face referire. Același lucru s-ar întâmpla dacă ai aloca un obiect unei constante și ai încerca să modifici orice proprietate a acestuia.
Dacă doriți să înghețați un array sau un obiect astfel încât să nu poată fi modificat, puteți folosi metoda Object.freeze, care face deja parte din ECMAScript 5.
const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
Răspunsul #3
Am dat peste acest articol în timp ce căutam de ce am putut să actualizez un Obiect chiar și după ce l-am definit ca const. Deci, ideea aici este că nu este Obiectul direct, ci atributele pe care le conține care pot fi actualizate.
De exemplu, obiectul meu arată astfel:
const number = {
id:5,
name:'Bob'
};
Răspunsurile de mai sus au subliniat corect că obiectul este constant și nu atributul său. Prin urmare, voi putea să actualizez id-ul sau numele făcând:
number.name = 'John';
Dar, nu voi putea să actualizez obiectul în sine astfel:
number = {
id:5,
name:'John'
};
TypeError: Assignment to constant variable.
Răspuns #4
Acesta este un comportament consecvent cu fiecare limbaj de programare la care mă pot gândi.
Luați în considerare C - tablourile sunt doar pointeri glorificați. Un tablou constant înseamnă doar că valoarea pointerului nu se va schimba - dar, de fapt, datele conținute la acea adresă sunt libere să se schimbe.
În JavaScript, ai voie să apelezi metodele obiectelor constante (desigur - altfel obiectele constante nu ar avea prea mult scop!) Aceste metode ar putea avea efectul secundar de a modifica obiectul. Deoarece tablourile în JavaScript sunt obiecte, acest comportament se aplică și pentru ele.
Singurul lucru de care ești sigur este că constanta va indica întotdeauna spre același obiect. Proprietățile obiectului în sine pot să se schimbe.
Răspunsul #5
Cuvântul cheie const este puțin înșelător.
Nu definește o valoare constantă. Definește o referință constantă la o valoare.
Din această cauză NU poți:
- Reatribuiți o valoare constantă
- Realocați un tablou constant
- Realocați un obiect constant
Dar POȚI:
- Schimbă un tablou constant
- Schimbă un obiect constant
