Fordi objekter i JavaScript er henvisninger værdier, du kan ikke bare kopi ved hjælp af =
. Men ingen bekymringer, her er 3 måder at klone et objekt på
# objekter er referencetyper
dit første spørgsmål kan være, hvorfor kan jeg ikke bruge =
. Lad os se, hvad der sker, hvis vi gør det:
const obj = { one: 1, two: 2 };const obj2 = obj;console.log( obj, // {one: 1, two: 2}; obj2, // {one: 1, two: 2};);
indtil videre ser begge objekter ud til at udsende den samme ting. Så intet problem, højre., Men lad os se, hvad der sker, hvis vi redigerer vores andet objekt:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! Jeg ændrede obj2
men hvorfor blev obj
også påvirket. Det skyldes, at objekter er referencetyper. Så når du bruger =
, kopierede den markøren til det hukommelsesrum, den optager. Referencetyper holder ikke værdier, de er en markør til værdien i hukommelsen.
Hvis du ønsker at lære mere om dette, tjek Gordons Watchhu ur og kode kursus. Det er gratis at tilmelde sig og se videoen “sammenligning med objekter”., Han giver en super fantastisk forklaring på det.
# 1. Brug Spread
brug spread vil klone dit objekt. Bemærk Dette vil være en lav kopi. Fra dette indlæg er spredningsoperatøren for kloningsobjekter i fase 4. Så det er ikke officielt i specifikationerne endnu. Så hvis du skulle bruge dette, skulle du kompilere det med Babel (eller noget lignende).
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. Ved Hjælp Af Objekt.tildel
Alternativt Object.assign
er i den officielle frigivet, og vil også skabe en overfladisk kopi af objektet.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
Bemærk den tomme {}
som det første argument, dette vil sikre, at du ikke mutere det oprindelige objekt 👍
# 3. Brug af JSON
denne sidste måde giver dig en dyb kopi. Nu vil jeg nævne, dette er en hurtig og beskidt måde at dybt klone et objekt på. For en mere robust løsning, vil jeg anbefale at bruge noget som lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
Her er en kommentar fra fællesskabet. Ja, det var til mit tidligere indlæg, hvordan man dybt kloner et Array ., Men ideen gælder stadig for objekter.
Alfredo Salzillo : jeg vil gerne have dig til at bemærke, at der er nogle forskelle mellem deepClone og JSON.stringify/parse.
- JSON.stringify / parse kun arbejde med nummer og streng og objekt bogstavelig uden funktion eller Symbol egenskaber.
- deepClone arbejde med alle typer, funktion og Symbol kopieres ved henvisning.
Her er et eksempel:
@OlegVaraksin : JSON-metoden har problemer med cirkulære afhængigheder. Endvidere kan rækkefølgen af egenskaber i det klonede objekt være anderledes.,
# Shallo.Clone vs Deep Clone
da jeg brugte spread ...
for at kopiere et objekt opretter jeg kun en lav kopi. Hvis arrayet er indlejret eller multidimensionelt, fungerer det ikke. Her er vores eksempel vil vi bruge:
const nestedObject = { flag: '🇨🇦', country: { city: 'vancouver', },};
# Overfladisk Kopi
Lad os klon vores objekt ved hjælp af spredning:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
Så har vi ændret vores klonede objekt ved at ændre byen. Lad os se udgangen.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
en overfladisk kopi betyder, at det første niveau kopieres, dybere niveauer refereres.,
# Deep Copy
lad os tage det samme eksempel, men anvende en dyb kopi ved hjælp af “JSON”
som du kan se, er den dybe kopi en sand kopi for indlejrede objekter. Ofte er tiden lav kopi god nok, du behøver ikke rigtig en dyb kopi. Det er som en neglepistol mod en hammer. Det meste af tiden er hammeren helt fin. Ved hjælp af en søm pistol for nogle små kunst og håndværk er ofte tilfældet en overkill, en hammer er fint. Det handler om at bruge det rigtige værktøj til det rigtige job
# Performance
desværre kan jeg ikke skrive en test for spredning, fordi den ikke officielt er i spec endnu., Ikke desto mindre inkluderede jeg det i testen, så du kan køre det i fremtiden 😝. Men resultatet viser Object.assign
er meget hurtigere endJSON
.
præstationstest
# community Input
# objekt.Tildel vs Spread
@d9el : det er vigtigt at bemærke, at objektet.assign er en funktion, der ændrer og returnerer målobjektet. I Samanthas eksempel ved hjælp af følgende er
const cloneFood = Object.assign({}, food);
{}
det objekt, der er ændret., Målobjektet refereres ikke til af nogen variabel på det tidspunkt, men fordi Object.assign
returnerer målobjektet, er vi i stand til at gemme det resulterende tildelte objekt i variablen cloneFood
. Vi kan skifte vores eksempel bruger du følgende:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
det er Klart, værdien af beef
i vores mad objekt er forkert, så kan vi tildele den korrekte værdi af beef
hjælp Object.assign
., Vi bruger faktisk ikke den returnerede værdi af funktionen overhovedet, men vi ændrer vores målobjekt, som vi har refereret til med const food
.
spredning på den anden side er en operatør, der kopierer egenskaber af et objekt til et nyt objekt., Hvis vi ønskede at kopiere ovenstående eksempel anvender spredt til at ændre vores variabel food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
får vi en fejl, fordi vi bruger sprede sig, når du opretter nye objekter, og derfor er tildele et helt nyt objekt food
, som blev erklæret med const
, som er ulovlig., Så vi kan enten vælge at erklære en ny variabel til at holde vores nye objekt i, som følgende:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
eller vi kunne erklære food
med let
eller var
, som ville give os mulighed for at tildele et helt nyt objekt:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
Tak: @d9el
# Dybt Klon ved hjælp af Eksterne Biblioteker
# Flere Måder ved hjælp af JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
kloner objektet.
Skriv et svar