Pentru obiecte în JavaScript sunt referințe valorile, nu poți pur și simplu doar să copiați folosind =
. Dar nu vă faceți griji, aici sunt 3 moduri pentru tine de a clona un obiect 👍
# Obiecte sunt Tipurile de Referință
prima întrebare ar putea fi, de ce nu pot folosi =
. Să vedem ce se întâmplă dacă facem asta:
const obj = { one: 1, two: 2 };const obj2 = obj;console.log( obj, // {one: 1, two: 2}; obj2, // {one: 1, two: 2};);
până în prezent, ambele obiect pare să emită același lucru. Deci, nici o problema, dreapta., Dar să vedem ce se întâmplă dacă edităm al doilea obiect:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! Am schimbat obj2
dar de ce a fost de asemenea afectat obj
. Asta pentru că obiectele sunt tipuri de referință. Deci, atunci când utilizați =
, a copiat indicatorul în spațiul de memorie pe care îl ocupă. Tipurile de referință nu dețin valori, ele sunt un indicator al valorii din memorie.dacă doriți să aflați mai multe despre acest lucru, consultați cursul Zhu Watch and Code al lui Gordon. Este gratuit să vă înscrieți și să vizionați videoclipul „comparație cu obiecte”., El dă o explicație super-minunat pe ea.
# 1. Utilizarea Spread
utilizarea spread va clona obiectul. Rețineți că aceasta va fi o copie superficială. Din acest post, operatorul de răspândire pentru clonarea obiectelor este în etapa 4. Deci nu este încă oficial în specificații. Deci, dacă ar fi să utilizați acest lucru, va trebui să-l compilați cu Babel (sau ceva similar).
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. Folosind Obiect.atribuiți
alternativ, Object.assign
este în oficial lansat și va crea, de asemenea, o copie superficială a obiectului.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
Notă gol {}
ca prim argument, acest lucru va asigura că nu evolua obiectul original 👍
# 3. Folosind JSON
Acest mod final vă va oferi o copie profundă. Acum voi menționa, acesta este un mod rapid și murdar de clonare profundă a unui obiect. Pentru o soluție mai robustă, mi-ar recomandăm să utilizați ceva de genul lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
Aici e un comentariu din partea comunității. Da, a fost pentru postul meu anterior, cum să clonați adânc o matrice ., Dar ideea se aplică în continuare obiectelor.Alfredo Salzillo: aș vrea să rețineți că există unele diferențe între deepClone și JSON.stringify/analiza.
- JSON.stringify / parse funcționează numai cu număr și șir și obiect literal fără proprietăți De funcție sau simbol.
- munca deepClone cu toate tipurile, funcția și simbolul sunt copiate prin referință.
Iată un exemplu:
@OlegVaraksin: metoda JSON are probleme cu dependențele circulare. Mai mult, ordinea proprietăților din obiectul clonat poate fi diferită.,
# Shallow Clone vs Deep Clone
când am folosit spread ...
pentru a copia un obiect, creez doar o copie shallow. Dacă matricea este imbricată sau multidimensională, nu va funcționa. Aici e exemplul nostru vom folosi:
const nestedObject = { flag: '🇨🇦', country: { city: 'vancouver', },};
# Copie Superficială
Să clona nostru obiect folosind răspândirea:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
Așa că ne-am schimbat clonat obiect de schimbarea orașului. Să vedem ieșirea.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
o copie superficială înseamnă că primul nivel este copiat, nivelurile mai profunde sunt referite.,
# copie profundă
să luăm același exemplu, dar aplicând o copie profundă folosind „JSON”
după cum puteți vedea, copia profundă este o copie adevărată pentru obiectele imbricate. Adesea, copia superficială a timpului este suficient de bună, nu aveți nevoie de o copie profundă. E ca un pistol de unghii vs un ciocan. De cele mai multe ori ciocanul este perfect în regulă. Folosind un pistol de unghii pentru unele arte mici și ambarcațiuni este adesea cazul o nejustificată, un ciocan este bine. Este vorba despre utilizarea instrumentului potrivit pentru jobul potrivit 🤓
# performanță
Din păcate, nu pot scrie un test pentru răspândire, deoarece nu este încă oficial în spec., Cu toate acestea, l-am inclus în test, astfel încât să îl puteți rula în viitor 😝. Dar rezultatul arată Object.assign
este mult mai rapid decât JSON
.
Test de performanță
# intrare comunitară
# obiect.assign vs Spread
@d9el: este important să rețineți că obiectul.assign este o funcție care modifică și returnează obiectul țintă. În Samanthei exemplu, folosind următoarele,
const cloneFood = Object.assign({}, food);
{}
este obiectul care este modificat., Obiectul țintă nu este referit de nicio variabilă în acel moment, ci pentru că Object.assign
returnează obiectul țintă, putem stoca obiectul atribuit rezultat în variabila cloneFood
. Am putea trece exemplul nostru și de a folosi următoarele:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
în mod Evident, valoarea de beef
în mâncarea noastră obiect este greșit, astfel încât să putem atribui valoarea corectă a beef
cu ajutorul Object.assign
., Nu folosim deloc valoarea returnată a funcției, dar modificăm Obiectul nostru țintă la care am făcut referire cu const food
.
Spread pe de altă parte este un operator care copiază proprietățile unui obiect într-un obiect nou., Dacă am vrut să copieze exemplul de mai sus folosind răspândit pentru a modifica variabila food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
vom obține o eroare, pentru că vom folosi răspândit atunci când crearea de noi obiecte, și, prin urmare, a desemnat un nou obiect la food
care a fost declarat cu const
, ceea ce este ilegal., Deci, putem alege fie să declare o nouă variabilă care să ne țină nouă obiect, cum ar fi următoarele:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
sau am putea declara food
cu let
sau var
care ne-ar permite să atribuiți un nou obiect:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
Multumesc: @d9el
# Adânc Clona folosind Biblioteci Externe
# Mai multe Moduri, folosind JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
clone obiect.
Lasă un răspuns