# 3 sposoby klonowania obiektów w JavaScript

wpis w: Articles | 0

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 obj2ale 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.assignjest 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.assignzwraca 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

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *