- vừa được xem lúc

JavaScript Shallow Copy so với Deep Copy: Ví dụ và Best practice tốt nhất

0 0 2

Người đăng: Thái Thịnh

Theo Viblo Asia

Sao chép cấu trúc dữ liệu là một công việc phổ biến khi làm việc với các đối tượng và mảng trong JavaScript. Tuy nhiên, các nhà phát triển thường gặp khó khăn khi quyết định giữa Shallow Copy và Deep Copy, việc hiểu sai sự khác biệt có thể dẫn đến những tác dụng phụ không mong muốn trong mã của bạn.

Shallow Copy là gì?

Một bản Shallow Copy chỉ tạo ra một đối tượng mới với các bản sao của các thuộc tính cấp cao nhất của đối tượng gốc. Đối với các thuộc tính là kiểu nguyên thủy (ví dụ: số, chuỗi, boolean), giá trị của nó sẽ được sao chép. Tuy nhiên, đối với các thuộc tính là đối tượng (như mảng hoặc đối tượng lồng nhau), chỉ có tham chiếu được sao chép — chứ không phải dữ liệu thực tế.

Điều này có nghĩa là trong khi đối tượng mới có bản sao riêng của các thuộc tính cấp cao nhất thì các đối tượng hoặc mảng lồng nhau vẫn được chia sẻ giữa bản gốc và bản sao.

VD:

const original = { name: "Alice", details: { age: 25, city: "Wonderland" }
}; // Shallow copy
const shallowCopy = { ...original }; // Modify the nested object in the shallow copy
shallowCopy.details.city = "Looking Glass"; // Original object is also affected
console.log(original.details.city); // Output: "Looking Glass"

Cách tạo một bản Shallow Copy

1. Sử dụng toán tử spread (...):

 const shallowCopy = { ...originalObject };

2. Sử dụng Object.assign():

 const shallowCopy = Object.assign({}, originalObject);

Mặc dù các phương pháp này nhanh chóng và dễ dàng, nhưng chúng không phù hợp với các đối tượng lồng nhau sâu.

Deep copy là gì?

Một bản Deep Copy sẽ sao chép mọi thuộc tính và thuộc tính con của đối tượng gốc. Điều này đảm bảo rằng bản sao hoàn toàn độc lập với bản gốc và các thay đổi đối với bản sao không ảnh hưởng đến đối tượng gốc.

Deep copy là điều cần thiết khi xử lý các cấu trúc dữ liệu phức tạp như đối tượng hoặc mảng lồng nhau, đặc biệt là trong các trường hợp mà tính toàn vẹn dữ liệu là rất quan trọng.

VD:

const original = { name: "Alice", details: { age: 25, city: "Wonderland" }
}; // Deep copy using JSON methods
const deepCopy = JSON.parse(JSON.stringify(original)); // Modify the nested object in the deep copy
deepCopy.details.city = "Looking Glass"; // Original object remains unchanged
console.log(original.details.city); // Output: "Wonderland"

Cách tạo một bản Deep Copy

1. Sử dụng JSON.stringify() và JSON.parse():

Chuyển đổi đối tượng thành một chuỗi JSON và sau đó phân tích cú pháp nó trở lại thành một đối tượng mới. Tuy nhiên, phương pháp này có những hạn chế: không thể xử lý các tham chiếu vòng và bỏ qua các thuộc tính như hàm, undefined hoặc Symbol.

 const deepCopy = JSON.parse(JSON.stringify(originalObject));

2. Sử dụng Thư viện:

Các thư viện như Lodash cung cấp các phương thức sao chép sâu mạnh mẽ.

 const _ = require('lodash'); const deepCopy = _.cloneDeep(originalObject);

3. Hàm đệ quy tùy chỉnh:

Để kiểm soát hoàn toàn, bạn có thể viết một hàm đệ quy để sao chép các đối tượng lồng nhau.

So sánh Shallow Copy và Deep Copy

image.png

Khi nào nên sử dụng Shallow Copy?

  • Đối tượng phẳng: Khi xử lý các đối tượng đơn giản không có thuộc tính lồng nhau.
  • Hiệu suất: Khi tốc độ là rất quan trọng và bạn không cần xử lý dữ liệu lồng nhau sâu.
  • Thay đổi tạm thời: Khi bạn định sửa đổi các thuộc tính cấp cao nhất nhưng chia sẻ dữ liệu lồng nhau.

VD: Sao chép đối tượng cài đặt của người dùng để thực hiện các điều chỉnh nhanh chóng:

const userSettings = { theme: "dark", layout: "grid" };
const updatedSettings = { ...userSettings, layout: "list" };

Khi nào nên sử dụng Deep Copy?

  • Cấu trúc phức tạp: Đối với các đối tượng có nhiều cấp độ lồng nhau.
  • Tránh tác dụng phụ: Khi bạn cần đảm bảo rằng các thay đổi trong bản sao không ảnh hưởng đến bản gốc.
  • Quản lý trạng thái: Trong các framework như React hoặc Redux, nơi tính bất biến là rất quan trọng.

VD: Nhân đôi trạng thái của trò chơi hoặc ứng dụng:

const gameState = { level: 5, inventory: { weapons: ["sword", "shield"], potions: 3 }
}; // Deep copy ensures no side effects
const savedState = JSON.parse(JSON.stringify(gameState));

Những sai lầm và cạm bẫy thường gặp

  • Cho rằng Shallow Copy luôn đủ: Các nhà phát triển thường sử dụng sai các phương pháp shallow copy cho các đối tượng lồng nhau, dẫn đến những thay đổi không mong muốn trong dữ liệu gốc.
  • Lạm dụng phương thức JSON: Mặc dù JSON.stringify/JSON.parse đơn giản, nhưng nó không hoạt động cho tất cả các đối tượng (ví dụ: những đối tượng chứa phương thức hoặc tham chiếu vòng).
  • Bỏ qua hiệu suất: Các phương thức deep copy có thể chậm hơn, đặc biệt là đối với các đối tượng lớn, vì vậy hãy sử dụng chúng một cách thận trọng.

Kết luận

Hiểu được sự khác biệt giữa shallow copy và deep copy là điều cần thiết để viết mã JavaScript không có lỗi. Shallow copy hiệu quả cho các cấu trúc phẳng, trong khi deep copy là không thể thiếu đối với các đối tượng phức tạp, lồng nhau. Hãy chọn phương pháp phù hợp dựa trên cấu trúc dữ liệu và nhu cầu ứng dụng của bạn và tránh các cạm bẫy tiềm ẩn bằng cách biết các hạn chế của từng phương pháp.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 528

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 436

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 158

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 149

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 113

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 249