Shallow Copy vs Deep Copy trong JavaScript

JavaScript xử lý việc sao chép theo hai cách tùy thuộc vào kiểu dữ liệu.

Các giá trị nguyên thủy (Copy by Value)

Các kiểu nguyên thủy bao gồm string, number, boolean, symbol, bigInt, và null. Khi bạn sao chép một giá trị nguyên thủy, JavaScript sẽ tạo ra một phiên bản độc lập mới trong bộ nhớ.

Ví dụ:

let a = 10;
let b = a;
b = 20;

Kết quả: a vẫn là 10.

Các giá trị không nguyên thủy (Copy by Reference)

Objectarray hoạt động theo cách khác. Chúng sử dụng tham chiếu (references). Khi bạn sao chép một object, bạn chỉ sao chép con trỏ trỏ đến vị trí của nó trong bộ nhớ.

Ví dụ:

let original = { name: "YOO" };
let copy = original;
copy.name = "NEW";

Kết quả: original.name bây giờ là "NEW".

Sự khác biệt: Shallow vs Deep

Shallow copy (sao chép nông) sao chép cấp độ cao nhất của một object. Nếu object đó có các object lồng nhau, nó vẫn trỏ đến các tham chiếu lồng nhau ban đầu. Deep copy (sao chép sâu) tạo ra một object hoàn toàn mới với tất cả các giá trị mới.

Hãy tưởng tượng nó giống như một chiếc pizza:

  • Shallow Copy: Bạn và một người bạn cùng chia sẻ một chiếc pizza. Nếu bạn của bạn ăn một miếng, chiếc pizza cũng sẽ nhỏ đi đối với bạn.
  • Deep Copy: Cả hai đều có những chiếc pizza riêng biệt. Nếu bạn của bạn ăn một miếng, chiếc pizza của bạn vẫn giữ nguyên.

Phương pháp Shallow Copy

Bạn có thể sử dụng toán tử spread (...) để tạo một shallow copy.

let original = { name: "YOO", details: { age: 22 } };
let copy = { ...original };

Cảnh báo: Nếu bạn thay đổi original.details.age, thì copy.details.age cũng sẽ thay đổi. Đây chính là "cạm bẫy" của shallow copy.

Các phương pháp Deep Copy

1. structuredClone()

Đây là một hàm có sẵn trong các trình duyệt hiện đại và Node.js. Nó xử lý các cấu trúc lồng nhau một cách hoàn hảo.

Ưu điểm:

  • Nhanh và là hàm native.
  • Xử lý được Date, RegExp, và Map.

Nhược điểm:

  • Sẽ thất bại nếu object chứa các function hoặc DOM nodes.

2. JSON.parse(JSON.stringify())

Đây là một mẹo cũ, trong đó bạn chuyển đổi một object thành một chuỗi (string) rồi chuyển ngược lại thành một object.

Tại sao nên tránh nó:

  • Nó làm mất các dữ liệu như undefined, Map, Set, hoặc Infinity.
  • Nó có thể làm sai lệch một số giá trị nhất định.

Source: https://dev.to/yogesh_992/shallow-copy-vs-deep-copy-in-java-script-explained-in-easiest-way-3dg5