MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Obiecte constante - Interzicerea modificării obiectului

Limbajul JavaScript permite modificarea dinamică a proprietăților obiectelor, adăugarea de noi proprietăți și metode la obiecte sau ștergerea celor deja existente. Cu toate acestea, astfel de modificări ale obiectelor pot fi nedorite. JavaScript furnizează trei mecanisme pentru a gestiona acest lucru:

Interzicerea extensiei obiectelor

Metoda `Object.preventExtensions()` permite interzicerea extensiei unui obiect, adică nu se pot adăuga noi proprietăți și metode în obiectul respectiv. Metoda primește ca parametru obiectul țintă.

Pentru exemplu:

const tom = {name: "Tom"};
// adăugăm în obiectul tom o nouă proprietate - company
tom.company = "Localhost";

console.log(`Nume: ${tom.name}  Companie: ${tom.company}`); // Nume: Tom  Companie: Localhost

Aici se adaugă o nouă proprietate `company` la obiectul `tom`. După adăugare, aceasta poate fi utilizată.

Acum, vom interzice extinderea folosind metoda `Object.preventExtensions()`:

const tom = {name: "Tom"};
Object.preventExtensions(tom);  // interzicem extinderea obiectului tom
tom.company = "Localhost";  // încercăm să adăugăm o nouă proprietate în obiectul tom
console.log(`Nume: ${tom.name}  Companie: ${tom.company}`); // Nume: Tom  Companie: undefined

Chiar dacă încercăm să definim o nouă proprietate pentru obiect, aceasta nu va fi adăugată. În încercarea de a accesa o astfel de proprietate, vom primi `undefined`.

Uneori poate apărea necesitatea de a verifica dacă un obiect este extensibil. De exemplu, dacă un obiect este extensibil, putem adăuga proprietăți în el și apoi să le utilizăm. Pentru a verifica extensibilitatea, se poate folosi metoda `Object.isExtensible()`. Aceasta primește ca parametru obiectul testat și, dacă obiectul suportă extinderea, metoda returnează `true`, altfel returnează `false`:

const tom = {name: "Tom"};
console.log(Object.isExtensible(tom));  // true
Object.preventExtensions(tom);  // interzicem extinderea obiectului tom
console.log(Object.isExtensible(tom));  // false

Închiderea obiectelor

Închiderea (sealing) sau "sigilarea" obiectelor permite, de asemenea, interzicerea extinderii obiectelor. Cu toate acestea, în plus, ea interzice și modificarea proprietăților deja existente. Pentru a sigila obiecte, se folosește metoda `Object.seal()`.

Să vedem mai întâi ce putem face cu un obiect fără a aplica `Object.seal()`:

const tom = {name: "Tom"};

// pentru proprietatea name interzicem modificarea
Object.defineProperty(tom, "name", { writable: false});
tom.name = "Tomas";

// adăugăm o nouă proprietate - age
tom.age = 39;
console.log(`Nume: ${tom.name}  Vârstă: ${tom.age}`);  // Nume: Tom  Vârstă: 39

// pentru proprietatea name permitem modificarea
Object.defineProperty(tom, "name", { writable: true});
tom.name = "Tomas";
console.log(`Nume: ${tom.name}  Vârstă: ${tom.age}`);  // Nume: Tomas  Vârstă: 39

Deci, putem modifica configurarea unei proprietăți (aici facem proprietatea `name` indisponibilă pentru scriere). De asemenea, putem adăuga o nouă proprietate în obiect.

Acum, să aplicăm metoda `Object.seal()`:

const tom = {name: "Tom"};
Object.seal(tom);       // sigilăm obiectul tom împotriva extinderii și modificării configurației
// pentru proprietatea name interzicem modificarea
Object.defineProperty(tom, "name", { writable: false});
tom.name = "Tomas";

// adăugăm o nouă proprietate - age
tom.age = 39;
console.log(`Nume: ${tom.name}  Vârstă: ${tom.age}`);  // Nume: Tom  Vârstă: undefined

// pentru proprietatea name permitem modificarea
Object.defineProperty(tom, "name", { writable: true}); // Uncaught TypeError: Cannot redefine property: name

După sigilarea obiectului cu `Object.seal(tom)`, nu vom putea adăuga o nouă proprietate în obiect. Prin urmare, în exemplul de mai sus, proprietatea `tom.age` va fi `undefined`. De asemenea, nu vom putea modifica din nou configurarea proprietății. Astfel, în acest caz, la al doilea apel al metodei `Object.defineProperty()` pentru proprietatea `name`, vom primi eroarea "Uncaught TypeError: Cannot redefine property: name".

Pentru a verifica dacă un obiect este sigilat, putem utiliza metoda `Object.isSealed()`. Dacă obiectul este sigilat, metoda returnează true. Trebuie menționat că, deoarece un obiect sigilat nu poate fi extins, metoda `Object.isExtensible()` returnează false pentru el:

const tom = {name: "Tom"};
console.log(Object.isExtensible(tom));  // true
console.log(Object.isSealed(tom));      // false
Object.seal(tom);       // închidem obiectul tom
console.log(Object.isExtensible(tom));  // false
console.log(Object.isSealed(tom));      // true

Interdicția de modificare a valorilor proprietăților

Congelarea (freezing) permite interzicerea modificării valorilor proprietăților, adică face obiectul complet constant. Astfel, doar definirea unui obiect ca o constantă obișnuită cu ajutorul operatorului `const` nu este suficient. De exemplu:

const tom = {name: "Tom"};
tom.name= "Tomas";
console.log(tom.name);  // Tomas

Aici observăm că proprietatea obiectului și-a schimbat valoarea, chiar dacă obiectul este definit ca o constantă.

Operatorul `const` afectează doar atribuirea unei noi valori constantei, așa cum se vede în exemplul următor:

const tom = {name: "Tom"};
tom = {name: "Sam"};    // Eroare - nu se poate atribui o valoare constantului a doua oară

Cu toate acestea, valorile proprietăților obiectului le putem schimba.

Pentru a face obiectul cu adevărat constant, este necesar să aplicăm metoda specială `Object.freeze()`. Această metodă primește ca parametru obiectul pe care dorim să îl facem constant:

const tom = {name: "Tom"};
Object.freeze(tom);
tom.name= "Tomas";      // nu se poate schimba valoarea proprietății
console.log(tom.name);   // Tom

Pentru a verifica dacă putem schimba valorile proprietăților obiectului, utilizăm metoda `Object.isFrozen()`. Dacă valorile proprietăților nu pot fi schimbate, aceasta returnează `true`.

Trebuie menționat că un obiect "înghețat" este cel mai înalt nivel de restricție a modificărilor la obiect. Prin urmare, un astfel de obiect nu poate fi extins și, de asemenea, nu se poate schimba configurația proprietăților sale.

const tom = {name: "Tom"};
console.log(Object.isExtensible(tom));  // true
console.log(Object.isSealed(tom));      // false
console.log(Object.isFrozen(tom));      // false
Object.freeze(tom);
console.log(Object.isExtensible(tom));  // false
console.log(Object.isSealed(tom));      // true
console.log(Object.isFrozen(tom));      // true
← Lecția anterioară Lecția următoare →