2012-07-02 2 views
30

Eventuali duplicati:
What is the most efficient way to clone a JavaScript object?JavaScript Object profonda copia

Ho un oggetto come questo:

User = {  
    name: "user", 
    settings: { 
    first: "1", 
    second: "2"  
    }  
} 

e un secondo:

user1 = { 
    name: "user1", 
    settings: { 
    second: "3" 
    } 
} 

ora voglio copiare i valori personalizzati di user1 in uso, utilizza:

for(var key in user1){ 
     User[key] = user1[key]; 
    } 

all'Utente risultato sarà:

User = { 
    name: "user1", 
    settings: { 
    second: "3" 
    } 
} 

User.settings è stato completamente sostituire, mentre io volevo solo settings.second da sostituire.

Come ottenere ciò senza sapere quanti oggetti figlio hanno l'oggetto principale?

+2

Utilizzare la ricorsione? Hai cercato funzioni di Object.copy profonde? – Bergi

+0

Puoi usare jQuery? –

+0

A causa del modo in cui javascript trasferisce gli oggetti (per riferimento), la copia profonda di un oggetto nidificato è in realtà una vera e propria prova. Seguivo il consiglio di @ Bergi e trovo uno preesistente. –

risposta

14

Ho trovato che il modo migliore per andare è questo:

http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/

Object.deepExtend = function(destination, source) { 
    for (var property in source) { 
    if (typeof source[property] === "object" && 
    source[property] !== null) { 
     destination[property] = destination[property] || {}; 
     arguments.callee(destination[property], source[property]); 
    } else { 
     destination[property] = source[property]; 
    } 
    } 
    return destination; 
}; 


Object.extend(destination, source); 

Che dire di questo?

function clone(destination, source) { 
     for (var property in source) { 
      if (typeof source[property] === "object" && source[property] !== null && destination[property]) { 
       clone(destination[property], source[property]); 
      } else { 
       destination[property] = source[property]; 
      } 
     } 
    }; 
+1

arguments.callee è deprecato. Dovresti davvero usare una funzione con nome. Inoltre, hai dimenticato hasOwnProperty che è abbastanza essenziale. – Bergi

+0

vedi l'aggiornamento, è meglio? –

+0

Sì, anche se si copiano ancora le proprietà dal prototipo. E la copia su un oggetto di destinazione dovrebbe essere chiamata "estendere", non "clonare" (il "deepextend" dal tuo primo tentativo sarebbe ancora meglio) – Bergi

-1

Questo è veramente hacky, ma dovrebbe funzionare. Suggerisco di fare come gli altri utenti hanno suggerito nei commenti; trova una libreria preesistente che farà questo per te.

for(var key in user1){ 
    var temp = User[key] 
    User[key] = user1[key]; 
    for(var key1 in temp){ 
     if(User[key][key1] == null){ 
     User[key][key1] = temp[key1]; 
     } 
    } 
} 
+0

l'oggetto che ho postato è un esempio sono alla ricerca di qualcosa che funzionerà ovunque –

+1

O ok. Bene darei un'occhiata a jQuerys http://api.jquery.com/jQuery.extend/, sembra che possa fare esattamente quello che stai cercando. –

+0

ho trovato questo che sembra funzionare (non perfetto ma un inizio) http://my.opera.com/GreyWyvern/blog/show.dml/1725165, per jquery mi piacerebbe kkep it agnostic framework –

4

afferrato metodo extend di jQuery, e ne ha fatto biblioteca agnostico.

Gist: Library agnostic version of jQuery's Extend

sua avvolti in un costruttore Extender, in modo da non dover istanziare tutti i suoi metodi interni ogni volta che si chiama il metodo di estendere.

Disclaimer: Non l'ho provato molto. È fondamentalmente un clone 1: 1 di jQuery's ext(), tuttavia il tuo chilometraggio può variare.

Utilizzarlo in questo modo.

var user1 = { 
    name: "user1", 
    settings: { 
    first: "1", 
     second: {bar: 'foo'} 
    } 
}; 
var user2 = { 
    name: "user2", 
    settings: { 
    second: {foo:'bar'} 
    } 
}; 

/* merge user1 into User */ 
__extend(true, user1, user2); 

// Modifies the User object 
user1.settings.second.foo == 'bar'; // true 

// note, you can do assignment too. 
var newUser = __extend(true, user1, user2); 

See here for more documentation

+0

Questo potrebbe essere più lungo di altri soluzioni ma funziona in modo affidabile e funziona su entrambi i tipi di array e di oggetti. Grazie! –

+0

Questo mi ha aiutato nel rinoceronte .. evviva –