ponieważ obiekty w JavaScript są wartościami odniesienia, nie można po prostu skopiować za pomocą =
. Ale nie martw się, oto 3 sposoby, aby sklonować obiekt 👍
# obiekty są typami odniesienia
Twoje pierwsze pytanie może być, dlaczego nie mogę użyć =
. Zobaczmy, co się stanie, jeśli to zrobimy:
const obj = { one: 1, two: 2 };const obj2 = obj;console.log( obj, // {one: 1, two: 2}; obj2, // {one: 1, two: 2};);
do tej pory oba obiekty wydają się wyprowadzać to samo. Więc nie ma problemu., Ale zobaczmy, co się stanie, jeśli edytujemy Nasz drugi obiekt:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! Zmieniłem obj2
ale dlaczegoobj
również miało to wpływ. Dzieje się tak, ponieważ obiekty są typami odniesienia. Więc kiedy używasz =
, skopiował wskaźnik do zajmowanej przestrzeni pamięci. Typy referencji nie zawierają wartości, są wskaźnikiem do wartości w pamięci.
Jeśli chcesz dowiedzieć się więcej na ten temat, zajrzyj na kurs Zhu Watch and Code Gordona. Zarejestruj się i obejrzyj film „porównanie z obiektami”., Daje super niesamowite Wyjaśnienie na ten temat.
# 1. Użycie Spread
użycie spread spowoduje sklonowanie obiektu. Uwaga to będzie płytka Kopia. Od tego postu operator spreadu do klonowania obiektów jest w etapie 4. Więc to nie jest jeszcze oficjalnie w specyfikacji. Więc jeśli miałbyś tego użyć, musiałbyś skompilować go za pomocą Babel (lub czegoś podobnego).
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. Korzystanie Z Obiektu.Przypisz
alternatywnie, Object.assign
jest w oficjalnym wydaniu i utworzy również płytką kopię obiektu.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
zwróć uwagę na pusty{}
jako pierwszy argument zapewni to, że nie zmutujesz oryginalnego obiektu 👍
# 3. Używając JSON
ten ostateczny sposób da ci głęboką kopię. Teraz wspomnę, że jest to szybki i brudny sposób głębokiego klonowania obiektu. Lodash Lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
oto komentarz społeczności. Tak, to było dla mojego poprzedniego postu, jak głęboko klonować tablicę ., Ale pomysł nadal odnosi się do przedmiotów.
Alfredo Salzillo : chciałbym zauważyć, że istnieją pewne różnice między deepClone i JSON.stringify / parse.
- JSON.stringify / parse działa tylko z liczbą i ciągiem znaków i obiektami literalnymi bez właściwości funkcji lub symbolu.
- praca deepClone ze wszystkimi typami, funkcją i symbolem są kopiowane przez odniesienie.
oto przykład:
@OlegVaraksin : metoda JSON ma problemy z kołowymi zależnościami. Ponadto kolejność właściwości w sklonowanym obiekcie może być różna.,
# Shallow Clone vs Deep Clone
kiedy użyłem spread...
aby skopiować obiekt, tworzę tylko płytką kopię. Jeśli tablica jest zagnieżdżona lub wielowymiarowa, nie będzie działać. Oto nasz przykład, którego użyjemy:
const nestedObject = { flag: '🇨🇦', country: { city: 'vancouver', },};
# Shallow Copy
sklonujmy nasz obiekt używając spread:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
zmieniliśmy więc nasz sklonowany obiekt zmieniając miasto. Zobaczmy wyniki.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
płytka Kopia oznacza, że pierwszy poziom jest kopiowany, głębsze poziomy są odniesione.,
# głęboka Kopia
weźmy ten sam przykład, ale zastosowanie głębokiej kopii przy użyciu „JSON”
Jak widać, głęboka kopia jest prawdziwą kopią dla zagnieżdżonych obiektów. Często płytka Kopia czasu jest wystarczająco dobra, naprawdę nie potrzebujesz głębokiej kopii. To jak pistolet do gwoździ kontra młotek. Przez większość czasu młotek jest w porządku. Używanie pistoletu do gwoździ dla niektórych małych sztuk i rzemiosła często jest przesadą, młotek jest w porządku. Chodzi o użycie odpowiedniego narzędzia do właściwej pracy
# Performance
Niestety nie mogę napisać testu dla spreadu, ponieważ nie jest jeszcze oficjalnie w spec., Niemniej jednak włączyłem go do testu, abyś mógł go uruchomić w przyszłości 😝. Ale wynik pokazuje Object.assign
jest o wiele szybszy niż JSON
.
Test wydajności
# Community Input
# Object.assign vs Spread
@d9el: ważne jest, aby pamiętać, że obiekt.assign to funkcja, która modyfikuje i zwraca obiekt docelowy. W poniższym przykładzie,
const cloneFood = Object.assign({}, food);
{}
jest obiektem, który został zmodyfikowany., Do obiektu docelowego nie odwołuje się żadna zmienna w tym momencie, ale ponieważ Object.assign
zwraca obiekt docelowy, jesteśmy w stanie zapisać wynikowy przypisany obiekt do zmiennej cloneFood
. Możemy przełączyć nasz przykład i użyć następującego:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
oczywiście wartość beef
w naszym obiekcie food jest nieprawidłowa, więc możemy przypisać poprawną wartość beef
używając Object.assign
., W rzeczywistości w ogóle nie używamy zwracanej wartości funkcji, ale modyfikujemy nasz obiekt docelowy, do którego odwołaliśmy się za pomocą const food
.
Spread z drugiej strony jest operatorem kopiującym właściwości jednego obiektu do nowego obiektu., Jeśli chcemy skopiować powyższy przykład używając spread do modyfikacji naszej zmiennej food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
otrzymujemy błąd, ponieważ używamy spread podczas tworzenia nowych obiektów i dlatego przypisujemy cały nowy obiekt do food
, który został zadeklarowany za pomocą const
, co jest nielegalne., Tak więc możemy albo zadeklarować nową zmienną do przechowywania naszego nowego obiektu w, jak poniżej:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
lub możemy zadeklarować food
z let
lub var
co pozwoli nam przypisać cały nowy obiekt:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
dzięki: @d9el
# Deep Clone using external libraries
# more ways using JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
klonuje obiekt.
Dodaj komentarz