2015-03-05 17 views
11

Próbuję wykonać głęboką kopię obiektów zagnieżdżonych w javascript. Moja tablica wyglądać następującoTablica do głębokiego kopiowania obiektów zagnieżdżonych w javascript

var arr = [{name:"adam",age:"21"}, 
    {name:"freddie",age:"35",children:[{name:"mercury",age:"25"}]}, 
    {name:"jim",age:"35",children:[{name:"morrison",age:"25",children:[{name:"some", age:"40"}]}]} 
    ]; 

chcę zrobić głęboki kopię każdego obiektu wewnątrz tablicy, która chcę stworzyć dokładną kopię ARR do nowej tablicy, które nie powinny mieć odniesienie do obiektu. Głębokość tablicy jest również nieznana, ponieważ tablica dzieci może być na dowolnym poziomie. Przeszedłem przez ten link Copying of an array of objects to another Array without object reference in javascript(Deep copy), ale to mi nie pomogło. Wyszukałem go i znalazłem kilka rozwiązań w jQuery, ale to mi nie pomogło, ponieważ nie znam jQuery.

Próbowałem też wdrożenie go z rekursji, ale to nie działa zbyt http://ideone.com/kJi5X3

chcę to zrobić w javascript, tylko bez użycia jQuery lub cokolwiek. Jestem nowym użytkownikiem JavaScript, więc mogłem go pominąć, jeśli istnieje jakaś biblioteka lub prosta metoda. Proszę, pomóż mi rozwiązać ten problem. Z góry dziękuję.

+1

Połączyłeś się z pytaniem, które mogło zostać zamknięte jako duplikat i powiedziałem, że to nie pomogło - czy możesz wyjaśnić, dlaczego to nie pomogło, więc rozumiemy, dlaczego nie jest to duplikat tego? –

+0

Należy również zauważyć, że jQuery to _just javascript library_, jeśli istniało rozwiązanie jQuery, czy wykluczasz bibliotekę, podczas gdy inna jest akceptowalna? –

+0

@ James Thorpe - Nie zastanawiam się, czy jest jakikolwiek sposób to zrobić z rekursją lub jakąkolwiek inną logiką, której nie znam jQuery i chcę to zrobić JAK NAJSZYBCIEJ. – user2912611

Odpowiedz

24

Masz dwie główne opcje:

  1. Korzystając JSON.stringify i JSON.parse:

    var copy = JSON.parse(JSON.stringify(original)); 
    

    Ale Nigdy nie lubiłem tego. Przejazd w obie strony przez tekst jest w najlepszym razie nieefektywny i nie będzie poprawnie obsługiwać wartości Date, RegExp, undefined itp., Chyba że napiszesz zamiennik i reviver.

  2. Zastosowanie funkcji rekurencyjnej, coś takiego:

var toString = Object.prototype.toString; 
 
function deepCopy(obj) { 
 
    var rv; 
 

 
    switch (typeof obj) { 
 
     case "object": 
 
      if (obj === null) { 
 
       // null => null 
 
       rv = null; 
 
      } else { 
 
       switch (toString.call(obj)) { 
 
        case "[object Array]": 
 
         // It's an array, create a new array with 
 
         // deep copies of the entries 
 
         rv = obj.map(deepCopy); 
 
         break; 
 
        case "[object Date]": 
 
         // Clone the date 
 
         rv = new Date(obj); 
 
         break; 
 
        case "[object RegExp]": 
 
         // Clone the RegExp 
 
         rv = new RegExp(obj); 
 
         break; 
 
        // ...probably a few others 
 
        default: 
 
         // Some other kind of object, deep-copy its 
 
         // properties into a new object 
 
         rv = Object.keys(obj).reduce(function(prev, key) { 
 
          prev[key] = deepCopy(obj[key]); 
 
          return prev; 
 
         }, {}); 
 
         break; 
 
       } 
 
      } 
 
      break; 
 
     default: 
 
      // It's a primitive, copy via assignment 
 
      rv = obj; 
 
      break; 
 
    } 
 
    return rv; 
 
} 
 
var a = [1, {foo: "bar"}, ['a', 'b'], new Date()]; 
 
snippet.log(JSON.stringify(a)); 
 
var b = deepCopy(a); 
 
snippet.log(JSON.stringify(b));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Należy zauważyć, że powyższe stosuje ES5 dysponuje obecny na wszystkich nowoczesnych przeglądarkach, ale nie niektórych starszych, takich jak IE8 . Wszystkie powyższe funkcje można jednak spakować do starszych przeglądarek.

To nie próbuje zająć się niestandardowymi funkcjami konstruktora lub zachowaniem prototypów na obiektach w tablicy; czyni to znacznie bardziej skomplikowanym i niemożliwym do udoskonalenia bez konwencji, w jaki sposób wywołać te konstruktory dla operacji kopiowania. Możesz zbliżyć się, przypisując ten sam prototyp, ale to nie uwzględni logiki w funkcji konstruktora, a w szczególności dla funkcji skonfigurowanych jako zamknięcia w niej.

+0

Crowder, który działał bezbłędnie, dziękuję bardzo :) – user2912611

Powiązane problemy