2011-07-06 19 views
7

Mam następujący kod (używam libary jQquery):Może ktoś wyjaśnić mi ten JavaScript Object "kopia" zachowanie

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

Moje pytanie: Kiedy ja obj.key = jsonobj i zmienić wartości w nowym obj.key. Dlaczego wartości w jsonobj również się zmieniają? I jak tego uniknąć? (Chcę nową "kopię" jsonobj).

Zrobiłem ten przypadek testowy: http://jsfiddle.net/WSgVz/

+5

Znakomicie uformowane pytanie i testcase. To niewiarygodnie smutne, że jest to dziś tak rzadkie. –

Odpowiedz

3

To dlatego, że obiekt nie jest kopiowany. Właściwość obj.key będzie zawierała tylko odniesienie do obiektu, więc po przypisaniu czegoś do obj.key.test efekt jest taki sam jak przypisanie go do jsonobj.test.

Można użyć metody jQuery extend aby utworzyć kopię:

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

Spowoduje to skopiowanie wartości do nowo utworzonego obiektu ({}).

+3

Warto również zauważyć, że będziesz potrzebował '$ .extend (true, {}, jsonobj)' do głębokiej kopii (w przeciwieństwie do płytka kopia jednopoziomowa). – Domenic

+0

@ Domenic: Dobrze, dobrze wiedzieć o bardziej złożonych strukturach obiektów. – Guffa

2

Bo kiedy robisz obj.key = jsonobj, nie jest jakiś nowy, kopiowany obiekt w obj.key; to tylko odnośnik do jsonobj, który już istnieje. Więc zmiany na obj.key również zmienią się jsonobj, ponieważ w rzeczywistości są one tym samym.

1

To dlatego, że to bez kopiowania - istnieje tylko jeden obiekt, który jest referenced przez różne zmienne i właściwości. Kiedy wykonujesz obj.key = jsonobj, kopiujesz tylko odniesienie do tego samego obiektu.

1

Wszystkie obiekty w JavaScript są kopiowane przez odniesienie, czyli:

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

Jeśli chcesz obj.key != jsonobj, trzeba sklonować obiekt. Tworząc nowy obiekt:

obj.key = $.parseJSON(objstring); 

lub przy użyciu jQuery sklonować istniejący:

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

Ale nie wydaje mi się, że odpowiedź znajduje się za wyjściem drugiego dziennika .......... –

+0

Druga instrukcja dziennika jest po prostu błędna, na odpowiedź Domenica. Jeśli chcesz mieć poprawny plik console.log: 'console.log (JSON.stringify (jsonobj))' –

5

Chcę zająć mały kawałek tego, co dzieje się tutaj, ponieważ inni zrobili tak dobrze adresowania większych problemów odniesień do obiektu javascript:

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

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

Jest to wynikiem documented WebKit bug, że console.log instrukcje nie wyprowadzają obiektu w czasie wywoływania console.log, ale za jakiś czas później.

+0

Starałem się wyjaśnić, o co w tym czasie chodziło, więc proszę wyjaśnij wszystkie -1 głosy ... – Domenic

+0

oh, to tylko przyczyniło się do mojego poprzedniego błędnego zrozumienia sposobu, w jaki javascript obsługuje kopiowanie/delegowanie obiektów. dziękuję za wskazanie tego;). – Hans

+0

Zmieniono moje -1 na +1. W czasie głosowania nie miałeś tak szczegółowej odpowiedzi. Teraz mam jajko na twarzy. – used2could

Powiązane problemy