Điều quan trọng là phải hiểu =
toán tử trong JavaScript làm và không làm gì.
Nhà =
điều hành không tạo một bản sao của dữ liệu.
Các =
nhà điều hành tạo ra một mới tham khảo đến cùng một dữ liệu.
Sau khi bạn chạy mã gốc của mình:
var a = $('#some_hidden_var').val(),
b = a;
a
và b
bây giờ là hai tên khác nhau cho cùng một đối tượng .
Bất kỳ thay đổi nào bạn thực hiện đối với nội dung của đối tượng này sẽ được nhìn thấy giống hệt nhau cho dù bạn tham chiếu nó thông qua a
biến hay b
biến. Chúng là cùng một đối tượng.
Vì vậy, khi bạn cố gắng "hoàn nguyên" b
về a
đối tượng ban đầu bằng mã này:
b = a;
Mã thực sự không làm gì cả , bởi vì a
và b
hoàn toàn giống nhau. Mã giống như khi bạn viết:
b = b;
mà rõ ràng sẽ không làm gì cả.
Tại sao mã mới của bạn hoạt động?
b = { key1: a.key1, key2: a.key2 };
Ở đây bạn đang tạo một đối tượng hoàn toàn mới với {...}
đối tượng theo nghĩa đen. Đối tượng mới này không giống với đối tượng cũ của bạn. Vì vậy, bây giờ bạn đang đặt b
làm tham chiếu đến đối tượng mới này, đối tượng này sẽ thực hiện những gì bạn muốn.
Để xử lý bất kỳ đối tượng tùy ý nào, bạn có thể sử dụng một hàm sao chép đối tượng, chẳng hạn như hàm được liệt kê trong câu trả lời của Armand hoặc vì bạn đang sử dụng jQuery chỉ cần sử dụng $.extend()
hàm . Hàm này sẽ tạo bản sao nông hoặc bản sao sâu của một đối tượng. (Đừng nhầm lẫn điều này với $().clone()
phương pháp sao chép các phần tử DOM, không phải các đối tượng.)
Đối với một bản sao cạn:
b = $.extend( {}, a );
Hoặc một bản sao sâu:
b = $.extend( true, {}, a );
Sự khác biệt giữa bản sao cạn và bản sao sâu là gì? Một bản sao cạn tương tự như mã của bạn tạo một đối tượng mới với một đối tượng theo nghĩa đen. Nó tạo ra một đối tượng cấp cao nhất mới chứa các tham chiếu đến các thuộc tính giống như đối tượng ban đầu.
Nếu đối tượng của bạn chỉ chứa các kiểu nguyên thủy như số và chuỗi, thì bản sao sâu và bản sao nông sẽ làm chính xác điều tương tự. Nhưng nếu đối tượng của bạn chứa các đối tượng hoặc mảng khác được lồng vào bên trong nó, thì một bản sao cạn sẽ không sao chép các đối tượng lồng nhau đó, nó chỉ tạo ra các tham chiếu đến chúng. Vì vậy, bạn có thể gặp vấn đề tương tự với các đối tượng lồng nhau mà bạn gặp phải với đối tượng cấp cao nhất của mình. Ví dụ, cho đối tượng này:
var obj = {
w: 123,
x: {
y: 456,
z: 789
}
};
Nếu bạn tạo một bản sao cạn của đối tượng đó, thì thuộc x
tính của đối tượng mới của bạn là cùng một x
đối tượng từ bản gốc:
var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
Bây giờ các đối tượng của bạn sẽ giống như sau:
// 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
}
};
Bạn có thể tránh điều này bằng một bản sao sâu. Bản sao sâu tái diễn vào mọi đối tượng và mảng lồng nhau (và Ngày tháng trong mã của Armand) để tạo bản sao của các đối tượng đó giống như cách nó tạo bản sao của đối tượng cấp cao nhất. Vì vậy, thay đổi copy.x.y
sẽ không ảnh hưởng obj.x.y
.
Câu trả lời ngắn gọn: Nếu nghi ngờ, bạn có thể muốn có một bản sao sâu.
a
được đặt từ.val()
tôi giả sử nó là JSON (một chuỗi), không phải là một đối tượng - có đúng không? Bạn có sử dụngJSON.parse(a)
tại một số điểm để có được một đối tượng thực tế không?