MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Copierea și Compararea Obiectelor

Copierea obiectelor

Spre deosebire de datele de tipuri primitive, datele din obiecte sunt copiate prin referință. Ce înseamnă asta? Să luăm în considerare următorul exemplu:

const tom = { name: "Tom" };
const bob = tom;

// verificăm proprietatea name pentru ambele constante
console.log(tom.name);  // Tom
console.log(bob.name);  // Tom

// schimbăm proprietatea name pentru constanta bob
bob.name = "Bob";

// verificăm din nou proprietatea name pentru ambele constante
console.log("După modificare");
console.log(tom.name);  // Bob
console.log(bob.name);  // Bob

La început, se definește un obiect obișnuit numit tom cu o singură proprietate name. Apoi, atribuim valoarea acestui obiect constantei bob:

const bob = tom;

În acest caz, constanta bob primește o referință sau, să spunem, adresa constantei tom, astfel încât după această atribuire, ambele constante practic indică către același obiect în memorie. Prin urmare, modificările efectuate printr-o constantă, cum ar fi:

bob.name = "Bob";

Vor afecta și cealaltă constantă, tom:

console.log(tom.name);  // Bob

În plus, să adăugăm un nou element la obiect printr-una dintre constante:

const tom = { name: "Tom" };
const bob = tom;

// adăugăm constantei bob o nouă proprietate - age
bob.age = 37;

// și vedem că și pentru tom s-a adăugat o nouă proprietate
console.log(tom.age);   // 37

După adăugarea proprietății age constantei bob, putem observa că pentru constanta tom s-a adăugat aceeași proprietate, deoarece, din nou, ambele constante reprezintă același obiect.

Dar ce se întâmplă dacă dorim să copiem o proprietate a unui obiect, astfel încât ambele constante sau variabile să indice complet obiecte diferite, astfel încât modificările asupra unuia să nu afecteze celălalt? În acest caz, putem utiliza metoda încorporată Object.assign().

Metoda Object.assign()

Metoda Object.assign() primește doi parametri:

Object.assign(target, ...sources)

Primul parametru - target - reprezintă obiectul în care trebuie copiate proprietățile. Al doilea parametru - ...sources - este un set de obiecte din care trebuie copiate proprietățile (adică putem copia proprietăți din mai multe obiecte simultan).

Metoda returnează obiectul țintă în care au fost copiate proprietățile din obiectele surse.

De exemplu:

const tom = { name: "Tom", age: 37};
const bob = Object.assign({}, tom);
bob.name = "Bob";
bob.age = 41;
       
console.log(`Obiectul tom. Name: ${tom.name}   Age: ${tom.age}`);
console.log(`Obiectul bob. Name: ${bob.name}   Age: ${bob.age}`);

În acest caz, apelul Object.assign({}, tom) înseamnă că copiem datele din obiectul tom într-un obiect gol {}. Rezultatul acestei copieri devine obiectul bob. Important de menționat că acesta este un obiect cu totul diferit de tom. Orice modificări aduse constantei bob nu vor afecta constanta tom.

Iată rezultatul în consolă al programului:

Obiect tom. Nume: Tom   Vârstă: 37
Obiect bob. Nume: Bob   Vârstă: 41

Copierea din mai multe obiecte

Similar, putem copia date din mai multe obiecte:

const tom = { name: "Tom" };
const sam = { age: 37 };
const person = { height: 170 };
Object.assign(person, tom, sam);    // copiem din tom și sam în person
console.log(person);    // {height: 170, name: "Tom", age: 37}

Aici, toate proprietățile din obiectele tom și sam sunt copiate în obiectul person. Astfel, după copiere, obiectul person va avea trei proprietăți.

Copierea proprietăților cu același nume

Dacă obiectele din care facem copierea conțin proprietăți cu același nume, proprietățile din obiectele mai recente vor suprascrie proprietățile din obiectele mai vechi:

const tom = { name: "Tom", age: 37};
const sam = { age: 45};
const person = { height: 170};
Object.assign(person, tom, sam);
console.log(person);    // {height: 170, name: "Tom", age: 45}

Aici ambele obiecte - tom și sam - conțin proprietatea age, dar în obiectul person, proprietatea age este egală cu 45 - valoarea din obiectul sam, deoarece copierea din obiectul sam se face în ultimul rând.

Copierea proprietăților-obiect

Cu toate că Object.assign() funcționează excelent pentru obiecte simple, ce se întâmplă dacă proprietatea obiectului copiat reprezintă tot un obiect:

const tom = { name: "Tom", company: {title: "Microsoft"}};
const bob = Object.assign({}, tom);
bob.name = "Bob";
bob.company.title = "Google";
console.log(tom.name);          // Tom
console.log(tom.company.title);         // Google

Aici, proprietatea company a obiectului tom reprezintă un alt obiect cu o singură proprietate. În timpul copierii, obiectul bob nu primește o copie a valorii tom.company, ci primește o referință la acest obiect. Prin urmare, modificările aduse lui bob.company vor afecta și tom.company.

Copierea obiectului cu ajutorul operatorului spread (...)

Operatorul spread (...) permite descompunerea unui obiect în diverse perechi cheie-valoare, pe care le putem transmite către un alt obiect.

const tom = { name: "Tom", age: 37, company: "Google"};
const bob = {...tom}
bob.name = "Bob";
         
console.log(tom);   // {name: "Tom", age: 37, company: "Google"}
console.log(bob);   // {name: "Bob", age: 37, company: "Google"}

În acest caz, obiectului bob i se transmit copii ale proprietăților obiectului tom.

Dacă unele proprietăți ale noului obiect trebuie să aibă alte valori (așa cum este în exemplul de mai sus pentru proprietatea name), acestea pot fi specificate la sfârșit:

const tom = { name: "Tom", age: 37, company: "Google"};
const bob = {...tom, name: "Bob"};
         
console.log(bob);   // {name: "Bob", age: 37, company: "Google"}

După cum se poate vedea din exemplul anterior, ambele constante, după copiere, reprezintă referințe către obiecte diferite, și modificările asupra unuia dintre ele nu vor afecta celălalt obiect.

Cu toate acestea, dacă obiectele conțin obiecte încorporate, aceste obiecte încorporate vor reprezenta, din nou, referințe către același obiect în timpul copierii:

const tom = { name: "Tom", age: 37, company: {title: "Microsoft"}};
const bob = {...tom}
bob.name = "Bob";
bob.company.title = "Google";

console.log(`${tom.name} - ${tom.company.title}`);  // Tom - Google
console.log(`${bob.name} - ${bob.company.title}`);  // Bob - Google

Compararea obiectelor

Să comparăm două obiecte folosind operațiile standard de comparare și echivalență:

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

Ambii operatori, în acest caz, vor returna false, adică obiectele nu sunt egale. Chiar și dacă valorile proprietăților obiectelor ar fi aceleași, totuși, în ambele cazuri, vom obține false.

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

Totuși, ce se întâmplă dacă ambele constante (variabile) rețin o referință la același obiect:

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

În acest caz, în ambele situații vom obține true, deoarece valorile ambelor constante sunt egale, practic reprezentând același obiect.

← Lecția anterioară Lecția următoare →