Czy metoda slice() jest odpowiednia do klonowania tablic?

0

Chciałbym poprawnie sklonować tablicę a znalazłem taki przykład:
http://www.gex.pl/2011/kopiowanie-tablic-w-javascript/

    var tablica = [3, 2, 2, 1, 4];
    var kopiaTablicy = tablica;
    kopiaTablicy.sort();
    
    tablica = [3, 2, 2, 1, 4];
    kopiaTablicy = tablica.slice();
    kopiaTablicy.sort()

Z tego co wywnioskowałem to dany sposób zwraca drugą tablicę ale posortowaną.

Zamierzam wczytać dane z pliku.csv gdzie każda linia csv będzie obiektem a dane rozdzielone przecinkami będą zmiennymi w tym obiekcie.
Chce utworzyć tablice takich obiektów jako **STAŁĄ **tak żeby nie dało się nic tam zmienić.

A na klonie tej tablicy będę wykonywać różne operacje usunę część obiektów do np. wyświetlenia itp.
Natomiast jeśli będę chciał zrobić inny zestaw operacji to sklonuję nową tablicę i tam zastosuję inne filtry. Chodzi mi o to żeby tylko raz wczytać dane z pliku do tablicy obiektów żeby później móc ją klonować.

Jaki jest poprawny sposób klonowania tablic?
Mam jeszcze drugie pytanko: Jak zrobić stałą z tej tablicy?

2

Z tego co wywnioskowałem to dany sposób zwraca drugą tablicę ale posortowaną.

Nazwa sort dosyć jest niejednoznaczna, prawda? ;-)

Jaki jest poprawny sposób klonowania tablic?

slice jest poprawnym sposobem.

Jak zrobić stałą z tej tablicy?

Object.freeze?

0

Możesz też użyć spread operatora:

const arr = [1, 2, 3]
const arrCopy = [...arr]

lub

const arr = [1, 2, 3]
const arrCopy = Array.from(arr)

Ja bym się trzymał wersji ze spread operatorem - najlepiej pokazująca intencję i przy okazji najkrótsza, używanie .slice() do kopiowania tablicy jest podobnie nieczytelne jak używanie !! do castowania do boola (!!value zamiast Boolean(value)) .

Ale tak naprawdę rzadko zachodzi potrzeba ręcznego kopiowania tablicy, Array.prototype ma garść metod, które zawsze zwracają nową tablicę:

  • .map()
  • .reduce()
  • .reduceRight()
  • .filter()
  • .slice() (bo to nie tylko kopiuje tablicę, ale ogólnie tworzy nową tablicę z fragmentu tablicy wejściowej)
  • .concat()

Ogólnie modyfikowanie wartości tablicy (nawet skopiowanej) nie jest najelegantszym sposobem jej przetwarzania i utrudnia debugowanie i rozumowanie o kodzie (już nie mówiąc o tym, że imperatywne pętle typu for, for..of same w sobie nie sa zbyt czytelne).

1

Chce utworzyć tablice takich obiektów jako STAŁĄ tak żeby nie dało się nic tam zmienić.

BTW pamiętaj, że slice, map czy inne robią płytkie kopie. Tzn. jeśli masz np. [{a: 2}, {a: 3}, {a:5}], to jeśli zrobisz na tym slice, to zwraca ci nową tablicę, ale w środku będą te same obiekty tj. referencje do tych samych obiektów. Czyli jeśli będziesz ruszał jakiś obiekt głęboko, to zmieni się on i w kopii, i w oryginale:

const arr = [{a: 2}, {a: 3}, {a:5}];
const copy = arr.slice();
arr[0].a = 10;
console.log(copy[0]); // {a: 10}
console.log(arr[0] === copy[0]); // true (bo te same obiekty)

aczkolwiek same tablice będą dwiema niezależnymi listami elementów (które po prostu przez przypadek posiadają te same obiekty w sobie, ale można to zmienić:

copy[0] = {a: 123}; // przypisujemy nową referencję do zerowego elementu copy
console.log(arr[0] === copy[0]); // false
console.log(arr[0]); // {a: 10}
console.log(copy[0]); // {a: 123}
0

@LukeJL
Raczej:

copy[0] = Object.assign({}, copy[0], {a: 123})

lub:

copy[0] = { ...copy[0], a: 123 }

Bo nie musisz się zastanawiac czy pierwotny obiekt miał jedno czy więcej pól.

0

Możliwe, ale ja pisałem o tym tylko, że metoda slice zrobi płytką kopię, a sztuczki z Object.assign czy ... zaciemniały by przykładowy kod.

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