2011-07-06 3 views
7

Je le code suivant (j'utilise le libary jQquery):Quelqu'un peut-il me expliquer cet objet javascript comportement "copie"

var obj = {}; 
var objstring = '{"one":"one","two":"two","three":"three"}' 

// first console output 
console.log(objstring); 

var jsonobj = $.parseJSON(objstring); 

// second console output 
console.log(jsonobj); 

obj.key = jsonobj; 
obj.key.test = "why does this affect jsonobj? (even in the second console output)"; 

// third console output 
console.log(jsonobj); 

Ma Question: Quand je ne obj.key = jsonobj et je changer valeurs dans la nouvelle obj.key. Pourquoi les valeurs de jsonobj changent-elles aussi? Et comment pourrais-je éviter cela? (Je veux une nouvelle "copie" de jsonobj).

J'ai fait ce cas de test: http://jsfiddle.net/WSgVz/

+5

Excellente question formée et testcase. C'est incroyablement triste que ce soit si rare de nos jours. –

Répondre

3

C'est parce que l'objet est pas copié. La propriété obj.key ne contiendra qu'une référence à l'objet. Par conséquent, lorsque vous affectez un objet à obj.key.test, l'effet est le même que pour l'affecter à jsonobj.test.

Vous pouvez utiliser la méthode jQuery extend pour créer une copie:

obj.key = $.extend({}, jsonobj); 

Cela va copier les valeurs dans l'objet nouvellement créé ({}).

+3

A noter également que vous aurez besoin de '$ .extend (true, {}, jsonobj)' pour une copie en profondeur (par opposition à copie à un niveau peu profonde). – Domenic

+0

@Domenic: Bon point, c'est bon à savoir pour des structures d'objets plus complexes. – Guffa

2

Parce que quand vous faites obj.key = jsonobj, il n'y a pas un nouvel objet copié dans obj.key; c'est juste une référence à la jsonobj qui existe déjà. Donc, les changements à obj.key vont également changer jsonobj, parce qu'ils sont en fait la même chose.

1

C'est parce que est aucune copie en cours - il n'y a qu'un seul objet, qui est referenced par diverses variables et propriétés. Lorsque vous faites obj.key = jsonobj, vous copiez simplement la référence au même objet.

1

Tous les objets JavaScript sont copiés par référence, ce qui signifie:

var x = {}; 
var y = x; 
x.foo = 22; // y.foo also = 22 since y and x are the same object 

Si vous voulez obj.key != jsonobj, vous devez cloner l'objet. En créant un nouvel objet:

obj.key = $.parseJSON(objstring); 

ou en utilisant jQuery pour cloner l'existant:

obj.key = $.extend({}, jsonobj); 
+0

Mais je ne semble pas trouver la réponse derrière la sortie du deuxième journal .......... –

+0

la deuxième déclaration de journal est juste faux, par la réponse de Domenic. Si vous voulez un console.log valide: 'console.log (JSON.stringify (jsonobj))' –

5

Je veux adresser un petit morceau de ce qui se passe ici, puisque d'autres l'ont fait bien aborder les grandes questions de références d'objets JavaScript:

// second console output 
console.log(jsonobj); 

obj.key = jsonobj; 
obj.key.test = "why does this affect jsonobj? (even in the second console output)"; 

Ceci est le résultat d'un documented WebKit bug, que console.log Les instructions ne sortent pas l'objet au moment de l'appel console.log, mais plutôt quelque temps plus tard.

+0

J'ai essayé de rendre beaucoup plus clair ce que je recevais en ce moment, alors expliquez s'il vous plaît -1 votes ... – Domenic

+0

oh ok, cela a seulement contribué à mon ancienne fausse compréhension de la façon dont javascript gère la copie/délégation d'objets. merci de le signaler;). – Hans

+0

A changé mon -1 en +1. Au moment de mon vote, vous n'aviez pas une réponse aussi détaillée. Maintenant j'ai un oeuf sur mon visage. – used2could

Questions connexes