2013-04-26 19 views
32

Jak mogę skopiować każdy element tablicy (gdzie elementy są obiektami) do innej tablicy, aby były całkowicie niezależne? Nie chcę zmieniać elementu w jednej tablicy, aby wpłynąć na drugą.Kopiowanie tablicy obiektów do innej tablicy w javascript

+4

Duplikat: http://stackoverflow.com/questions/7486085/copying-array-by-value-in-javascript –

Odpowiedz

65

Jeśli docelowa tablica jeszcze nie istnieje, można użyć slice() lub concat(); slice() (lub slice(0), ale argumentów domyślnie 0) jest prawdopodobnie bardziej idiomatyczne:

var destinationArray = sourceArray.slice(); // Probably more idiomatic 
// or 
var destinationArray = sourceArray.concat(); 

Od ES2015 (aka ES6), istnieje również Array.from, który tworzy nową tablicę z niczego array-like (w tym rzeczywista array).

var destinationArray = Array.from(sourceArray); 

(Array.from można podkładano/polyfilled dla starszych silnikach JavaScript)

Po tym, oba zespoły będą miały te same treści. Zmiana jednej tablicy nie zmieni drugiej. Naturalnie, jeśli wpis tablicy jest obiektem, wpis dla tego obiektu w obu tablicach wskaże ten sam obiekt; nie jest to "głęboka" kopia.

Jeśli tablica docelowy istnieje i chcesz dołączyć zawartość tablicy źródłowej do niego, można użyć push:

destinationArray.push.apply(destinationArray, sourceArray); 

To działa poprzez wywołanie push na tablicy docelowej przy użyciu apply cechę JavaScript funkcje, które umożliwiają określenie argumentów dla wywołania funkcji jako tablicy. push przesunie tyle elementów, ile ma argumentów, więc kończy się kopiowaniem elementów z tablicy źródłowej do tablicy docelowej.

W ES2015 i później, można dokonać tego odkurzacza z notacją Spread (...):

destinationArray.push(...sourceArray); 

Oto wersja ES5:

var source1, dest1, source2, dest2; 
 

 
snippet.log("If dest doesn't exist yet:"); 
 
source1 = [1, 2, 3, 4]; 
 
dest1 = source1.slice(0); 
 
snippet.log("[before change] source1 = " + source1.join(", ")); 
 
snippet.log("[before change] dest1 = " + dest1.join(", ")); 
 
source1[2] = "three"; 
 
dest1[3] = "four"; 
 
snippet.log("[after change] source1 = " + source1.join(", ")); 
 
snippet.log("[after change] dest1 = " + dest1.join(", ")); 
 

 
snippet.log("If dest already exists and we're just appending:"); 
 
source2 = [1, 2, 3, 4]; 
 
dest2 = ['a', 'b', 'c', 'd']; 
 
snippet.log("[before append] source2 = " + source2.join(", ")); 
 
snippet.log("[before append] dest2 = " + dest2.join(", ")); 
 
dest2.push.apply(dest2, source2); 
 
snippet.log("[before change] source2 = " + source2.join(", ")); 
 
snippet.log("[before change] dest2 = " + dest2.join(", ")); 
 
source2[2] = "three"; 
 
dest2[7] = "four"; 
 
snippet.log("[after change] source2 = " + source2.join(", ")); 
 
snippet.log("[after change] dest2 = " + dest2.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

+1

Dzięki! Naprawdę pomogło to – hAlE

+0

Cóż, to nie działa na przykładzie, z którym mam do czynienia :( – hAlE

+0

Gdzie powinienem dodać kod, aby można było sprawdzić? – hAlE

3
var clonedArray = array.concat(); 
0

I sugeruje użycie concat(), jeśli używasz nodeJS. We wszystkich innych przypadkach stwierdziłem, że slice(0) działa dobrze.

14

łatwy sposób uzyskać tej pracy jest za pomocą:

var cloneArray = JSON.parse(JSON.stringify(originalArray)); 

mam problemy z uzyskaniem arr.concat() lub arr.splice(0) dać głęboki kopię. Powyższy fragment działa idealnie.

1

Jeśli chcesz zachować odniesienie:

Array.prototype.push.apply(destinationArray, sourceArray);

2

świetny sposób na sklonowanie tablicę jest z tablicy dosłownym a operatorem spread. Jest to możliwe dzięki ES2015.

let objArray = [{name:'first'}, {name:'second'}, {name:'third'}, {name:'fourth'}]; 

let clonedArr = [...objArray]; 

console.log(clonedArr) // [Object, Object, Object, Object] 

Można znaleźć tej opcji kopiowania w dokumentacji MDN dla rozpostartymi operatorówhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array

Jest również najlepiej praktykować Airbnb użytkownika. https://github.com/airbnb/javascript#es6-array-spreads

Uwaga: Zazwyczaj operatory rozprzestrzeniania w ES2015 mają jeden poziom głębokości podczas kopiowania tablicy. Dlatego nie nadają się do kopiowania wielowymiarowych tablic.

0

Istnieją dwie ważne uwagi.

  1. Używanie array.concat() nie działa przy użyciu Angular 1.4.4 i jQuery 3.2.1 (to jest moje środowisko).
  2. Obiekt array.slice(0). Jeśli więc zrobisz coś takiego jak newArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0), dwie nowe tablice będą odwoływać się do tylko jednej tablicy, a zmiana jednej będzie miała wpływ na drugą.

Alternatywnie, użycie spowoduje tylko skopiowanie wartości, dlatego za każdym razem tworzy nową tablicę.

Powiązane problemy