Czy dobrze wykonałem kopiowanie płytkie oraz głębokie?

0

Czy dobrze zaprezentowałem jak działa kopiowanie płytkie oraz głębokie? Pytam bo mam wrażenie, że coś mi tu nie pasuje.

// PŁYTKIE
const a = [1, 2, 3];
const b = a;
console.log(a);
console.log(b);
b[0] = 4;
console.log(a);
console.log(b);

console.log('-----------------------------------------');

// GŁĘBOKIE
const array1 = [1, 2, 3, 4, 5];
let array1Copy = array1;
console.log(array1);
console.log(array1Copy);
array1Copy = [6, 7, 8, 9, 10];
console.log(array1);
console.log(array1Copy);
1

Nie. Nie możesz użyć operatora =. Do głębokiego kopiowania stwórz np. tablicę obiektów. Sposobów na głębokie kopiowanie jest kilka, ale najprostszy to użycie JSON.stringify(), a potem JSON.parse(). Najpierw powinieneś zrozumieć co to referencja i co w rzeczywistości robisz.

0

Ok, poprawiłem to głębokie.

const array1 = [1, 2, 3];
const deepCopy = JSON.parse(JSON.stringify(array1));
deepCopy.push(4, 5);
console.log(array1, deepCopy);

A teraz wracając do płytkiego, to chyba nie rozumiem czegoś. Czy ono działa tylko na tablicach wielowymiarowych?

const tablica = [[1, 2]];
const kopia = [...tablica];
console.log(tablica, kopia);
tablica[0][1] = 10;
console.log(tablica, kopia);
1

Tablica jednowymiarowa może być płytko lub głęboko sklonowana, tylko w tym przypadku nie ma różnicy, bo masz tylko jedną operację faktycznego klonowania.

JSON.parse(JSON.stringify()) jest bardzo powolną metodą, w dodatku zgubi część danych (w json nie zapiszesz funkcji, undefined, obiektów będących instancjami czegoś innego niż Object). Lepszą opcją byłaby pętla i rekurencja, ale najpierw pasowałoby, żebyś zrozumiał to, co robisz. Przedstawię to na obrazku:

screenshot-20200228123953.png

Mamy na początku tablicę A, zawierającą dwie kolejne tablice: B i C.
Gdy wykonujesz kopiowanie płytkie - tworzysz nową tablicę D - jest ona taka sama jak A, ale nie ta sama. Pierwotnie obie zawierają te same, nie takie same elementy B i C. Jeżeli dodasz coś do tablicy A to nie będzie tego w tablicy D i odwrotnie. Ale jeżeli dodasz coś do tablicy B - to odczytując tablicę B zarówno poprzez A i D otrzymasz to samo. Czyli modyfikować tablicę B możesz teraz na 3 sposoby: B.push(), A[0].push() i D[0].push(). I tak samo odczytywać.

Prosta forma na "ręczne" skopiowanie wyglądałaby tak:

const A = [];
const B = [0, 1];
const C = [2, 3];
A.push(B, C);

const D = []; // nowa tablica
D.push(B, C); // wepchanie TYCH SAMYCH elementów

Zaproponowane przez Ciebie na początku D = A nie tworzy nowej tablicy, tylko nadaje drugą nazwę tej samej tablicy.

Formą sprawdzenia czy tablica jest tą samą, a nie taką samą jest użycie operatora ===.

A[0] === B[0]; /// true

Klonowanie głębokie różni się tym, że każdy element wgłąb (nawet jakby zagnieżdżenie tablic było jeszcze większe) jest taki sam, ale nie ten sam.

W kolejnym "prostym" kodzie posłużę się skróconym zapisem [...tablica], który tworzy nową tablicę, jednocześnie wypełniając ją wartościami z tej tablicy. Ale zanim do niego przejdziemy zaznaczę, że:

const A = [];
const B = [0, 1];
const C = [2, 3];
A.push(B, C);

const D = [...A];

Nadal sprawi, że tablice B i C są w dwóch tablicach A i D, ale to są dokładnie te same tablice.

Prosty przykład "ręczny" głębokiego kopiowania:

const A = [];
const B = [0, 1];
const C = [2, 3];
A.push(B, C);

const D = []; // nie wypełniamy zawartością, bo chcemy mieć też kopie B i C.

const E = [...B]; // robimy kopię wewnątrznych tablic
const F = [...C];
const D = [];
D.push(E, F);

Użyj ===, żeby sprawdzić, że faktycznie - choć E wygląda tak samo jak B - to są to różne tablice. Modyfikując jedną nie zmieniasz zawartości drugiej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1