JS Sao chép một đối tượng – Cách sao chép một Obj trong JavaScript


Đối tượng JavaScript là tập hợp các cặp khóa-giá trị. Nó là một kiểu dữ liệu không nguyên thủy có thể chứa nhiều kiểu dữ liệu khác nhau. Ví dụ:

const userDetails = {
  name: "John Doe",
  age: 14,
  verified: false
};

Khi làm việc với các đối tượng trong JavaScript, đôi khi bạn có thể muốn thay đổi giá trị hoặc thêm một thuộc tính mới cho đối tượng.

Trong một số trường hợp, trước khi bạn cập nhật hoặc thêm thuộc tính mới, bạn sẽ muốn tạo một đối tượng mới và sao chép hoặc sao chép giá trị của đối tượng ban đầu.

Ví dụ, nếu bạn muốn sao chép giá trị của userDetails đối tượng và sau đó đổi tên thành một cái gì đó khác. Theo nghĩa điển hình, bạn sẽ muốn sử dụng toán tử đẳng thức (=).

const newUser = userDetails;
console.log(newUser); // {name: 'John Doe', age: 14, verified: false}

Mọi thứ dường như vẫn ổn, nhưng hãy xem điều gì sẽ xảy ra nếu chúng ta chỉnh sửa đối tượng thứ hai của mình:

const newUser = userDetails;
newUser.name = "Jane Doe";

console.log(newUser); // {name: 'Jane Doe', age: 14, verified: false}

Mọi thứ đều ổn với đối tượng mới, nhưng nếu bạn cố gắng kiểm tra các giá trị của đối tượng ban đầu, bạn sẽ thấy nó bị ảnh hưởng. Tại sao? Thế nào?

console.log(userDetails); // {name: 'Jane Doe', age: 14, verified: false}

Đây là vấn đề. Đối tượng ban đầu bị ảnh hưởng bởi vì các đối tượng được các loại tài liệu tham khảo. Điều này có nghĩa là bất kỳ giá trị nào bạn lưu trữ trong bản sao hoặc đối tượng gốc đều trỏ đến cùng một đối tượng.

Đây không phải điều bạn muốn. Bạn muốn lưu trữ giá trị của một đối tượng trong một đối tượng mới và thao tác giá trị trong đối tượng mới mà không ảnh hưởng đến mảng ban đầu.

Trong bài viết này, bạn sẽ tìm hiểu ba phương pháp mà bạn có thể sử dụng để thực hiện việc này. Bạn cũng sẽ tìm hiểu ý nghĩa của các bản sao sâu và nông cũng như cách chúng hoạt động.

Trong trường hợp bạn đang vội, đây là ba phương pháp và một ví dụ về cách chúng hoạt động.

// Spread Method
let clone = { ...userDetails }

// Object.assign() Method
let clone = Object.assign({}, userDetails)

// JSON.parse() Method
let clone = JSON.parse(JSON.stringify(userDetails))

Nếu bạn không vội, hãy bắt đầu.🚀

Đọc thêm  Tìm hiểu phát triển toàn bộ ngăn xếp - HTML, CSS, JavaScript, Node.js, MongoDB

Cách sao chép một đối tượng trong JavaScript bằng toán tử trải rộng

Toán tử trải rộng đã được giới thiệu trong ES6 và có thể trải rộng các giá trị vào một đối tượng có ba dấu chấm ở phía trước.

// Declaring Object
const userDetails = {
  name: "John Doe",
  age: 14,
  verified: false
};

// Cloning the Object with Spread Operator
let cloneUser = { ...userDetails };

console.log(cloneUser); // {name: 'John Doe', age: 14, verified: false}

Điều này không còn được tham chiếu, nghĩa là việc thay đổi giá trị của đối tượng sẽ không ảnh hưởng đến đối tượng ban đầu.

// Cloning the Object with Spread Operator
let cloneUser = { ...userDetails };

// changing the value of cloneUser
cloneUser.name = "Jane Doe"

console.log(cloneUser.name); // 'Jane Doe'
console.log(cloneUser); // {name: 'Jane Doe', age: 14, verified: false}

Khi bạn kiểm tra giá trị tên trong đối tượng ban đầu hoặc toàn bộ đối tượng, bạn sẽ nhận thấy nó không bị ảnh hưởng.

console.log(userDetails.name); // 'John Doe'
console.log(userDetails); // {name: 'John Doe', age: 14, verified: false}

Ghi chú: Bạn chỉ có thể sử dụng cú pháp trải rộng để tạo một bản sao nông của một đối tượng trong khi các đối tượng sâu hơn được tham chiếu. Bạn sẽ hiểu khi chúng ta đến phần cuối cùng của bài viết này.

Cách sao chép một đối tượng trong JavaScript với Object.assign()

Một thay thế cho toán tử trải rộng là Object.assign() phương pháp. Bạn sử dụng phương thức này để sao chép các giá trị và thuộc tính từ một hoặc nhiều đối tượng nguồn sang đối tượng đích.

// Declaring Object
const userDetails = {
  name: "John Doe",
  age: 14,
  verified: false
};

// Cloning the Object with Object.assign() Method
let cloneUser = Object.assign({}, userDetails);

console.log(cloneUser); // {name: 'John Doe', age: 14, verified: false}

Điều này không còn được tham chiếu, nghĩa là việc thay đổi giá trị của đối tượng sẽ không ảnh hưởng đến đối tượng ban đầu.

// Cloning the Object with Object.assign() Method
let cloneUser = Object.assign({}, userDetails);

// changing the value of cloneUser
cloneUser.name = "Jane Doe"

console.log(cloneUser.name); // 'Jane Doe'
console.log(cloneUser); // {name: 'Jane Doe', age: 14, verified: false}

Khi bạn kiểm tra giá trị tên trong đối tượng ban đầu hoặc toàn bộ đối tượng, bạn sẽ nhận thấy nó không bị ảnh hưởng.

console.log(userDetails.name); // 'John Doe'
console.log(userDetails); // {name: 'John Doe', age: 14, verified: false}

Ghi chú: Bạn chỉ có thể sử dụng Object.assign() phương pháp để tạo một bản sao nông của một đối tượng trong khi các đối tượng sâu hơn được tham chiếu. Bạn sẽ hiểu khi chúng ta đến phần cuối cùng của bài viết này.

Cách sao chép một đối tượng bằng JSON.parse()

Phương thức cuối cùng là JSON.parse(). Bạn sẽ sử dụng phương pháp này cùng với JSON.stringify(). Bạn có thể sử dụng điều này để sao chép sâu, nhưng nó có một số nhược điểm. Đầu tiên, hãy xem nó hoạt động như thế nào.

// Declaring Object
const userDetails = {
  name: "John Doe",
  age: 14,
  verified: false
};

// Cloning the Object with JSON.parse() Method
let cloneUser = JSON.parse(JSON.stringify(userDetails));

console.log(cloneUser); // {name: 'John Doe', age: 14, verified: false}

Ngoài ra, giống như các phương pháp trước đó, điều này không còn được tham chiếu nữa. Điều này có nghĩa là bạn có thể thay đổi một giá trị trong đối tượng mới mà không ảnh hưởng đến đối tượng ban đầu.

// Cloning the Object with JSON.parse() Method
let cloneUser = JSON.parse(JSON.stringify(userDetails));

// changing the value of cloneUser
cloneUser.name = "Jane Doe"

console.log(cloneUser.name); // 'Jane Doe'
console.log(cloneUser); // {name: 'Jane Doe', age: 14, verified: false}

Khi bạn kiểm tra giá trị tên trong đối tượng ban đầu hoặc toàn bộ đối tượng, bạn sẽ nhận thấy nó không bị ảnh hưởng.

console.log(userDetails.name); // 'John Doe'
console.log(userDetails); // {name: 'John Doe', age: 14, verified: false}

Ghi chú: Phương pháp này có thể được sử dụng để nhân bản sâu nhưng sẽ không phải là lựa chọn tốt nhất vì nó không hoạt động với function hoặc symbol tính chất.

Đọc thêm  Cómo imprimir en la consola en JS

Bây giờ chúng ta hãy khám phá nhân bản nông và sâu và cách bạn có thể sử dụng JSON.parse() phương pháp thực hiện nhân bản sâu. Bạn cũng sẽ tìm hiểu lý do tại sao nó không phải là lựa chọn tốt nhất.

Bản sao nông so với Bản sao sâu

Cho đến nay, ví dụ được sử dụng trong bài viết này là một đối tượng cơ bản chỉ có một cấp độ. Điều này có nghĩa là chúng tôi chỉ thực hiện (các) bản sao nông. Nhưng khi một đối tượng có nhiều hơn một cấp độ, thì bạn sẽ được yêu cầu thực hiện một bản sao sâu.

// Shallow object
const userDetails = {
  name: "John Doe",
  age: 14,
  verified: false
};

// Deep object
const userDetails = {
  name: "John Doe",
  age: 14,
  status: {
    verified: false,
  }
};

Lưu ý rằng đối tượng sâu có nhiều cấp độ vì có một đối tượng khác trong userDetails vật. Một đối tượng sâu có thể có nhiều cấp độ như bạn muốn.

Ghi chú: Khi bạn sử dụng toán tử trải rộng hoặc Object.assign() để sao chép một đối tượng sâu, các đối tượng sâu hơn sẽ được tham chiếu.

const userDetails = {
  name: "John Doe",
  age: 14,
  status: {
    verified: false
  }
};

// Cloning the Object with Spread Operator
let cloneUser = { ...userDetails };

// Changing the value of cloneUser
cloneUser.status.verified = true;

console.log(cloneUser); // {name: 'John Doe', age: 14, status: {verified: true}}
console.log(userDetails); // {name: 'John Doe', age: 14, status: {verified: true}}

Bạn sẽ nhận thấy rằng cả đối tượng ban đầu và đối tượng mới đều bị ảnh hưởng bởi vì khi bạn sử dụng toán tử trải rộng hoặc Object.assign() để sao chép một đối tượng sâu, các đối tượng sâu hơn sẽ được tham chiếu.

Đọc thêm  Làm tổ cho các vòng lặp trong JavaScript

Làm thế nào bạn có thể khắc phục vấn đề này

Bạn có thể dùng JSON.parse() và mọi thứ sẽ hoạt động tốt.

const userDetails = {
  name: "John Doe",
  age: 14,
  status: {
    verified: false
  }
};

// Cloning the Object with Spread Operator
let cloneUser = JSON.parse(JSON.stringify(userDetails));

// Changing the value of cloneUser
cloneUser.status.verified = true;

console.log(cloneUser); // {name: 'John Doe', age: 14, status: {verified: true}}
console.log(userDetails); // {name: 'John Doe', age: 14, status: {verified: false}}

Nhưng có một vấn đề với phương pháp này. Vấn đề là bạn có thể mất dữ liệu của mình. Thế nào?

JSON.stringify() hoạt động rất tốt với các kiểu dữ liệu nguyên thủy như số, chuỗi hoặc Booleans và đó là những gì bạn đã thấy trong các ví dụ trước của chúng tôi. Nhưng đôi khi, JSON.stringify() là không thể đoán trước nếu bạn không biết về một số giá trị và cách nó xử lý chúng.

Ví dụ: nó không hoạt động với các chức năng, biểu tượng hoặc undefined các giá trị. Nó cũng thay đổi các giá trị khác như NanInfinity đến null, phá mã của bạn. Khi bạn có một hàm, ký hiệu hoặc giá trị không xác định, nó sẽ trả về một cặp khóa-giá trị trống và bỏ qua nó.

const userDetails = {
  name: "John Doe",
  age: 14,
  status: {
    verified: false,
    method: Symbol(),
    title: undefined
  }
};

// Cloning the Object with Spread Operator
let cloneUser = JSON.parse(JSON.stringify(userDetails));

Mọi thứ dường như hoạt động tốt, nhưng đối với đối tượng mới, JSON.stringify() sẽ không trả về cặp khóa-giá trị nào cho các giá trị ký hiệu và không xác định.

console.log(cloneUser); 

// Output
{
  name: "John Doe",
  age: 14,
  status: {
    verified: false
  }
};

Điều này có nghĩa là bạn cần phải cẩn thận. Tùy chọn tốt nhất để thực hiện nhân bản sâu là sử dụng Lodash. Sau đó, bạn có thể chắc chắn rằng không dữ liệu nào của mình sẽ bị mất.

const userDetails = {
  name: "John Doe",
  age: 14,
  status: {
    verified: false,
    method: Symbol(),
    title: undefined
  }
};

console.log(_.cloneDeep(userDetails));

Kết thúc!

Bài viết này đã hướng dẫn bạn cách sao chép một đối tượng trong JavaScript bằng ba phương pháp chính. Bạn đã thấy những phương pháp đó hoạt động như thế nào và khi nào thì sử dụng từng phương pháp. Bạn cũng đã học về nhân bản sâu.

Bạn có thể đọc bài viết này để hiểu tại sao JSON.parse(JSON.stringify()) là một cách làm không tốt để sao chép một đối tượng trong JavaScript.

Hãy mã hóa vui vẻ!



Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status