Ważne jest, aby zrozumieć, co robi =operator w JavaScript, a czego nie.
=Operator nie robi kopii danych.
=Operator tworzy nowe odniesienie do samego danych.
Po uruchomieniu oryginalnego kodu:
var a = $('#some_hidden_var').val(),
b = a;
ai bsą teraz dwiema różnymi nazwami dla tego samego obiektu .
Wszelkie zmiany wprowadzone w zawartości tego obiektu będą widoczne identycznie, niezależnie od tego, czy odwołujesz się do niego za pośrednictwem azmiennej, czy bzmiennej. To ten sam obiekt.
Tak więc, gdy później spróbujesz „przywrócić” boryginalny aobiekt za pomocą tego kodu:
b = a;
Kod właściwie nic nie robi , ponieważ ai bsą dokładnie tym samym. Kod jest taki sam, jak gdybyś napisał:
b = b;
co oczywiście nic nie da.
Dlaczego twój nowy kod działa?
b = { key1: a.key1, key2: a.key2 };
Tutaj tworzysz zupełnie nowy obiekt z {...}literałem obiektu. Ten nowy obiekt nie jest tym samym, co stary obiekt. Więc teraz ustawiasz bjako odniesienie do tego nowego obiektu, który robi to, co chcesz.
Aby obsłużyć dowolny obiekt, możesz użyć funkcji klonowania obiektu, takiej jak ta wymieniona w odpowiedzi Armanda, lub ponieważ używasz jQuery, po prostu użyj tej $.extend()funkcji . Ta funkcja utworzy płytką kopię lub głęboką kopię obiektu. (Nie myl tego z $().clone()metodą kopiowania elementów DOM, a nie obiektów).
W przypadku płytkiej kopii:
b = $.extend( {}, a );
Lub głęboka kopia:
b = $.extend( true, {}, a );
Jaka jest różnica między płytką kopią a głęboką kopią? Płytka kopia jest podobna do kodu, który tworzy nowy obiekt z literałem obiektu. Tworzy nowy obiekt najwyższego poziomu zawierający odniesienia do tych samych właściwości, co oryginalny obiekt.
Jeśli twój obiekt zawiera tylko prymitywne typy, takie jak liczby i łańcuchy, głęboka kopia i płytka kopia zrobią dokładnie to samo. Ale jeśli twój obiekt zawiera inne obiekty lub tablice zagnieżdżone w nim, to płytka kopia nie kopiuje tych zagnieżdżonych obiektów, a jedynie tworzy do nich odniesienia. Więc możesz mieć ten sam problem z zagnieżdżonymi obiektami, który miałeś z obiektem najwyższego poziomu. Na przykład biorąc pod uwagę ten obiekt:
var obj = {
w: 123,
x: {
y: 456,
z: 789
}
};
Jeśli zrobisz płytką kopię tego obiektu, wówczas xwłaściwość nowego obiektu będzie taka sama xjak oryginalnego:
var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
Teraz twoje obiekty będą wyglądać tak:
// copy looks as expected
var copy = {
w: 321,
x: {
y: 654,
z: 789
}
};
// But changing copy.x.y also changed obj.x.y!
var obj = {
w: 123, // changing copy.w didn't affect obj.w
x: {
y: 654, // changing copy.x.y also changed obj.x.y
z: 789
}
};
Możesz tego uniknąć dzięki głębokiej kopii. Głęboka kopia powtarza się do każdego zagnieżdżonego obiektu i tablicy (oraz daty w kodzie Armanda), aby utworzyć kopie tych obiektów w ten sam sposób, w jaki utworzyła kopię obiektu najwyższego poziomu. Więc zmiana copy.x.ynie wpłynie obj.x.y.
Krótka odpowiedź: w razie wątpliwości prawdopodobnie potrzebujesz głębokiej kopii.
azostał ustawiony z.val(), zakładam, że jest to JSON (ciąg znaków), a nie obiekt - czy to prawda? Czy używaszJSON.parse(a)kiedyś, aby uzyskać rzeczywisty obiekt?