JavaScript - Sao chép nông: Hướng dẫn dành cho người mới bắt đầu
Xin chào các pháp sư JavaScript tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình đầy thú vị vào thế giới sao chép nông trong JavaScript. Đừng lo lắng nếu bạn là người mới bắt đầu lập trình - tôi sẽ là người hướng dẫn thân thiện của bạn, giải thích mọi thứ từng bước. Vậy, hãy lấy một tách cà phê (hoặc đồ uống yêu thích của bạn), và chúng ta cùng bắt đầu!
什么是浅拷贝 (Shallow Copy)?
Trước khi chúng ta đi sâu vào chi tiết của sao chép nông, hãy bắt đầu với một ví dụ đơn giản. Hãy tưởng tượng bạn có một bức tranh đẹp, và bạn muốn làm một bản sao của nó. Bạn có hai lựa chọn:
- Chụp ảnh bức tranh (sao chép nông)
- Tạo lại toàn bộ bức tranh từ đầu (sao chép sâu)
Trong JavaScript, sao chép nông giống như việc chụp ảnh. Nó tạo ra một đối tượng hoặc mảng mới, nhưng các phần tử bên trong vẫn là tham chiếu đến các phần tử trong đối tượng gốc.
Cách hoạt động của sao chép nông
Khi bạn tạo một sao chép nông:
- Một đối tượng hoặc mảng mới được tạo ra
- Các thuộc tính cấp cao nhất được sao chép
- Các đối tượng hoặc mảng con vẫn được tham chiếu từ đối tượng gốc
Hãy cùng xem điều này trong hành động với một đoạn mã!
// Đối tượng gốc
let original = {
name: "Alice",
age: 30,
hobbies: ["reading", "swimming"]
};
// Sao chép nông
let shallowCopy = Object.assign({}, original);
// Thay đổi bản sao
shallowCopy.name = "Bob";
shallowCopy.hobbies.push("coding");
console.log(original);
console.log(shallowCopy);
Nếu bạn chạy đoạn mã này, bạn sẽ thấy điều thú vị:
{name: "Alice", age: 30, hobbies: ["reading", "swimming", "coding"]}
{name: "Bob", age: 30, hobbies: ["reading", "swimming", "coding"]}
Chú ý rằng thay đổi name
chỉ ảnh hưởng đến bản sao, nhưng thay đổi hobbies
ảnh hưởng đến cả hai đối tượng. Đó là bản chất của sao chép nông!
Sao chép sâu so với sao chép nông
Bây giờ chúng ta đã hiểu sao chép nông, hãy so sánh nó với anh em ruột của nó, sao chép sâu.
Tính năng | Sao chép nông | Sao chép sâu |
---|---|---|
Tạo mới đối tượng | Có | Có |
Sao chép thuộc tính cấp cao nhất | Có | Có |
Sao chép đối tượng/mảng con | Không (tham chiếu gốc) | Có (tạo bản sao mới) |
Hiệu suất | Nhanh hơn | Chậm hơn |
Sử dụng bộ nhớ | Ít | Nhiều |
Khi nào nên sử dụng sao chép nông
Sao chép nông rất hữu ích khi:
- Bạn chỉ cần thay đổi thuộc tính cấp cao nhất
- Hiệu suất là mối quan tâm
- Bạn muốn tạo một tham chiếu mới cho một đối tượng
Khi nào nên sử dụng sao chép sâu
Sao chép sâu tốt hơn khi:
- Bạn cần thay đổi thuộc tính con mà không ảnh hưởng đến gốc
- Bạn muốn một bản sao hoàn toàn độc lập của đối tượng
Ví dụ về sao chép nông trong JavaScript
Hãy cùng khám phá một số cách phổ biến để tạo sao chép nông trong JavaScript!
1. Object.assign()
let original = { a: 1, b: { c: 2 } };
let copy = Object.assign({}, original);
copy.a = 5;
copy.b.c = 10;
console.log(original); // { a: 1, b: { c: 10 } }
console.log(copy); // { a: 5, b: { c: 10 } }
Ở đây, Object.assign()
tạo một sao chép nông. Thay đổi a
chỉ ảnh hưởng đến bản sao, nhưng thay đổi b.c
ảnh hưởng đến cả hai đối tượng vì nó là thuộc tính con.
2. Dấu ba chấm (Spread Operator (...))
let fruits = ["apple", "banana", ["grape", "orange"]];
let fruitsCopy = [...fruits];
fruitsCopy[0] = "pear";
fruitsCopy[2].push("kiwi");
console.log(fruits); // ["apple", "banana", ["grape", "orange", "kiwi"]]
console.log(fruitsCopy); // ["pear", "banana", ["grape", "orange", "kiwi"]]
Dấu ba chấm tạo một sao chép nông của mảng. Thay đổi phần tử đầu tiên chỉ ảnh hưởng đến bản sao, nhưng thêm vào mảng con ảnh hưởng đến cả hai.
3. Array.from()
let numbers = [1, 2, [3, 4]];
let numbersCopy = Array.from(numbers);
numbersCopy[0] = 10;
numbersCopy[2].push(5);
console.log(numbers); // [1, 2, [3, 4, 5]]
console.log(numbersCopy); // [10, 2, [3, 4, 5]]
Array.from()
cũng tạo một sao chép nông. Các phần tử cấp một được sao chép, nhưng các mảng con vẫn được tham chiếu.
Tầm quan trọng của sao chép nông
Bạn có thể tự hỏi, "Tại sao chúng ta cần sao chép nông?" Câu hỏi tuyệt vời! Sao chép nông rất hữu ích trong nhiều tình huống:
-
Hiệu suất: Sao chép nông nhanh hơn và sử dụng ít bộ nhớ hơn so với sao chép sâu, làm cho nó lý tưởng cho các đối tượng lớn hoặc các thao tác thường xuyên.
-
Vô đổi: Nó giúp duy trì tính vô đổi trong mã của bạn, điều này rất quan trọng cho việc quản lý trạng thái dự đoán được trong các khung công tác JavaScript hiện đại.
-
Tránh tác dụng phụ: Sao chép nông cho phép bạn thay đổi một đối tượng mà không thay đổi trực tiếp đối tượng gốc, giảm thiểu các tác dụng phụ không mong muốn trong mã của bạn.
-
React và Redux: Trong các ứng dụng React và Redux, sao chép nông thường được sử dụng để kích hoạt lại渲染 và cập nhật trạng thái mà không thay đổi dữ liệu gốc.
Dưới đây là một ví dụ thực tế:
function updateUserProfile(user, newName) {
// Tạo một sao chép nông của đối tượng người dùng
let updatedUser = Object.assign({}, user);
// Cập nhật tên
updatedUser.name = newName;
return updatedUser;
}
let user = {
name: "Alice",
age: 30,
address: {
city: "Wonderland",
street: "Rabbit Hole Lane"
}
};
let updatedUser = updateUserProfile(user, "Alicia");
console.log(user); // Đối tượng người dùng gốc không thay đổi
console.log(updatedUser); // Đối tượng mới với tên được cập nhật
Trong ví dụ này, chúng ta đang cập nhật tên của người dùng mà không thay đổi đối tượng gốc. Đây là một mẫu phổ biến trong quản lý trạng thái và giúp duy trì tính toàn vẹn dữ liệu.
Kết luận
Chúc mừng! Bạn đã vừa bước những bước đầu tiên vào thế giới sao chép nông trong JavaScript. Nhớ rằng, sao chép nông giống như việc chụp ảnh nhanh - nó nhanh và hiệu quả, nhưng không capture tất cả chi tiết.
Trong hành trình JavaScript của bạn, bạn sẽ tìm thấy nhiều tình huống nơi sao chép nông rất hữu ích. Nó là một công cụ mạnh mẽ trong bộ công cụ lập trình của bạn, đặc biệt khi làm việc với các cấu trúc dữ liệu phức tạp và quản lý trạng thái.
Hãy tiếp tục thực hành, giữ vững sự tò mò và đừng ngại thử nghiệm. Trước khi bạn biết, bạn sẽ tạo và thao tác các đối tượng như một chuyên gia!
Chúc bạn may mắn và hy vọng rằng các bản sao của bạn luôn ở mức độ nông (hoặc sâu) như bạn cần! ?
Credits: Image by storyset