2012-07-02 4 views
30

Possible en double:
What is the most efficient way to clone a JavaScript object?Javascript objet de copie profonde

J'ai un objet comme celui-ci:

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

et une seconde:

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

maintenant je veux copier les valeurs personnalisées de util_1 dans l'utilisateur, en utilisant:

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

l'Utilisateur résultat sera:

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

USER.settings a été entièrement remplacer alors que je voulais seulement settings.second être remplacé.

Comment y parvenir, sans connaître l'objet enfant de l'objet principal?

+2

Utiliser la récursion? Avez-vous recherché des fonctions Object.copy profondes? – Bergi

+0

Pouvez-vous utiliser jQuery? –

+0

En raison de la façon dont javascript passe des objets autour (par référence), la copie en profondeur d'un objet imbriqué est en fait une épreuve. Je suivrais le conseil de Bergi et en trouverais un déjà existant. –

Répondre

14

J'ai trouvé que la meilleure façon de faire est la suivante:

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); 

Qu'en est-ce?

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 est obsolète. Vous devriez vraiment utiliser une fonction nommée. En outre, vous avez oublié hasOwnProperty qui est tout à fait essentiel. – Bergi

+0

voir la mise à jour, c'est mieux? –

+0

Oui, bien que vous copiez toujours les propriétés du prototype. Et copier sur un objet de destination devrait être appelé "étendre", pas "cloner" (le "deepextend" de votre premier essai serait encore mieux) – Bergi

-1

Ceci est vraiment hacky, mais cela devrait fonctionner. Je suggère de faire comme les autres utilisateurs l'ont suggéré dans les commentaires; Trouver une bibliothèque préexistante qui le fera pour vous.

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'objet que j'ai posté était un exemple je suis à la recherche de quelque chose qui fonctionnera partout –

+1

O ok. Eh bien, je voudrais jeter un oeil à jQuerys http://api.jquery.com/jQuery.extend/, il semble que cela puisse faire exactement ce que vous cherchez. –

+0

J'ai trouvé ce qui semble fonctionner (pas parfait mais un début) http://my.opera.com/GreyWyvern/blog/show.dml/1725165, pour jquery je voudrais le kkep framework agnostique –

4

Récupère la méthode extend de jQuery et la rend indépendante de la bibliothèque.

Contenu essentiel: Library agnostic version of jQuery's Extend

Son enveloppé dans un constructeur de Extender, de sorte que vous n'avez pas à instancier toutes ses méthodes internes à chaque fois que vous appelez la méthode extend.

Avis de non-responsabilité: Je n'ai pas testé cela de manière approfondie. Il s'agit essentiellement d'un clone 1: 1 de extend() de jQuery, mais votre kilométrage peut varier.

Utilisez-le comme ceci.

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

Cela peut être plus long que d'autres solutions, mais cela fonctionne de manière fiable et fonctionne à la fois sur les types de tableau et d'objet. Je vous remercie! –

+0

Cela m'a aidé dans rhino .. acclamations –

Questions connexes