eftersom objekt i JavaScript är referensvärden kan du inte bara kopiera med =
. Men inga bekymmer, här är 3 sätt för dig att klona ett objekt
# objekt är referenstyper
din första fråga kan vara, varför kan jag inte använda =
. Låt oss se vad som händer om 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};);
hittills verkar båda objekten mata ut samma sak. Så inga problem, eller hur., Men låt oss se vad som händer om vi redigerar vårt andra objekt:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! Jag ändrade obj2
men varför påverkadesobj
också. Det beror på att objekt är referenstyper. Så när du använder =
kopierade den pekaren till det minnesutrymme den upptar. Referenstyper håller inte värden, de är en pekare till värdet i minnet.
om du vill veta mer om detta, kolla in Gordons Zhu Watch and Code course. Det är gratis att registrera och titta på videon ”jämförelse med objekt”., Han ger en super fantastisk förklaring på det.
# 1. Använda Spread
använda spread kommer att klona ditt objekt. Observera att detta kommer att vara en grund kopia. Från och med detta inlägg är spridningsoperatören för kloningsobjekt i steg 4. Så det är inte officiellt i specifikationerna än. Så om du skulle använda det här måste du sammanställa det med Babel (eller något liknande).
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. Använda Objekt.tilldela
alternativt är Object.assign
I den officiella utgåvan och kommer också att skapa en grund kopia av objektet.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
notera det tomma{}
som det första argumentet kommer det att säkerställa att du inte muterar det ursprungliga objektet
# 3. Använda JSON
detta sista sätt kommer att ge dig en djup kopia. Nu ska jag nämna, detta är ett snabbt och smutsigt sätt att djupt klona ett objekt. Lodash Lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
här är en kommentar från gemenskapen. Ja, det var för mitt tidigare inlägg, Hur man djupt klona en Array ., Men tanken gäller fortfarande objekt.
Alfredo Salzillo : jag vill att du noterar att det finns vissa skillnader mellan deepClone och JSON.stringify/tolka.
- JSON.stringify / parse fungerar endast med nummer och sträng och objekt bokstavligt utan funktion eller Symbolegenskaper.
- deepclone fungerar med alla typer, funktioner och symboler kopieras med referens.
här är ett exempel:
@OlegVaraksin : JSON-metoden har problem med cirkulära beroenden. Dessutom kan ordningen på Egenskaper i det klonade objektet vara annorlunda.,
# Shallow Clone vs Deep Clone
När jag använde spread...
för att kopiera ett objekt skapar jag bara en grund kopia. Om arrayen är kapslad eller flerdimensionell, fungerar det inte. Här är vårt exempel som vi kommer att använda:
const nestedObject = { flag: '🇨🇦', country: { city: 'vancouver', },};
# Shallow Copy
låt oss klona vårt objekt med spread:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
Så vi ändrade vårt klonade objekt genom att ändra staden. Låt oss se utgången.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
en grund kopia innebär att den första nivån kopieras, djupare nivåer refereras.,
# Deep Copy
låt oss ta samma exempel men tillämpa en djup kopia med ”JSON”
som du kan se är den djupa kopian en sann kopia för kapslade objekt. Ofta tid Grunt kopia är tillräckligt bra, du behöver inte verkligen en djup kopia. Det är som en spikpistol mot en hammare. För det mesta är hammaren helt bra. Att använda en nagelpistol för några små konster och hantverk är ofta fallet en overkill, en hammare är bara bra. Det handlar om att använda rätt verktyg för rätt jobb
# prestanda
tyvärr kan jag inte skriva ett test för spridning eftersom det inte är officiellt i spec ännu., Ändå inkluderade jag det i testet så att du kan köra det i framtiden. Men resultatet visar Object.assign
är mycket snabbare änJSON
.
Performance Test
# Community Input
# Object.tilldela vs Spread
@d9el : det är viktigt att notera det objektet.tilldela är en funktion som ändrar och returnerar målobjektet. I Samantha exempel med hjälp av följande,
const cloneFood = Object.assign({}, food);
{}
är objektet som ändras., Målobjektet refereras inte av någon variabel vid den punkten, men eftersomObject.assign
returnerar målobjektet kan vi lagra det resulterande tilldelade objektet i variabelncloneFood
. Vi kan byta upp vårt exempel och använda följande:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
självklart är värdet på beef
I vårt livsmedelsobjekt fel, så vi kan tilldela rätt värde för beef
med Object.assign
., Vi använder faktiskt inte det returnerade värdet av funktionen alls, men vi ändrar vårt målobjekt som vi har refererat till med const food
.
Spread å andra sidan är en operatör som kopierar egenskaper för ett objekt till ett nytt objekt., Om vi ville replikera ovanstående exempel med hjälp av spread för att ändra vår variabel food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
får vi ett fel, eftersom vi använder spread när vi skapar nya objekt och därför tilldelar ett helt nytt objekt till food
som förklarades vara med const
, vilket är olagligt., Så vi kan antingen välja att deklarera en ny variabel för att hålla vårt nya objekt I, som följande:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
eller så kan vi förklara food
med let
eller var
vilket skulle tillåta oss att tilldela ett helt nytt objekt:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
Tack: @d9el
# djup klon med externa bibliotek
# fler sätt att använda JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
kloner objektet.
Lämna ett svar