Giới Thiệu Về Object.assign()

Trong JavaScript, Object.assign() là một phương thức mạnh mẽ được sử dụng để sao chép các thuộc tính từ một hoặc nhiều đối tượng nguồn vào một đối tượng đích. Nó cho phép sao chép nông (shallow copy) các thuộc tính, giúp hợp nhất các đối tượng hoặc bổ sung các thuộc tính vào một đối tượng hiện có. Đây là một công cụ hữu ích khi làm việc với các đối tượng trong JavaScript, đặc biệt khi cần kết hợp nhiều đối tượng hoặc nhân bản chúng mà không thay đổi giá trị gốc.

Cú Pháp Của Object.assign()

Cú pháp của Object.assign() như sau:

Object.assign(target, ...sources);

Trong đó:

  • target: Đối tượng đích mà các thuộc tính sẽ được sao chép vào.
  • sources: Một hoặc nhiều đối tượng nguồn từ đó các thuộc tính sẽ được sao chép sang đối tượng đích.

Phương thức trả về đối tượng đích đã được sao chép các thuộc tính từ các nguồn.

Ví Dụ Cơ Bản

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(returnedTarget);  // { a: 1, b: 4, c: 5 }
console.log(target);          // { a: 1, b: 4, c: 5 }

Trong ví dụ này, các thuộc tính từ đối tượng source được sao chép vào đối tượng target. Lưu ý rằng thuộc tính b bị ghi đè từ giá trị 2 thành 4 do source.b = 4.

Các Trường Hợp Sử Dụng Object.assign()

1. Sao Chép Một Đối Tượng

Khi cần sao chép một đối tượng, Object.assign() giúp bạn tạo một bản sao của đối tượng mà không thay đổi giá trị ban đầu. Đây là sao chép nông, chỉ sao chép các thuộc tính tầng ngoài của đối tượng.

const obj = { a: 1, b: 2 };
const copy = Object.assign({}, obj);

console.log(copy);  // { a: 1, b: 2 }

2. Kết Hợp Nhiều Đối Tượng

Bạn có thể kết hợp nhiều đối tượng thành một đối tượng đích duy nhất bằng cách sử dụng Object.assign().

const obj1 = { a: 1 };
const obj2 = { b: 2 };
const obj3 = { c: 3 };

const combined = Object.assign({}, obj1, obj2, obj3);

console.log(combined);  // { a: 1, b: 2, c: 3 }

Trong ví dụ này, Object.assign() kết hợp cả ba đối tượng obj1, obj2, và obj3 vào một đối tượng đích duy nhất.

3. Ghi Đè Các Thuộc Tính

Khi một đối tượng đích có cùng thuộc tính với một trong các đối tượng nguồn, thuộc tính từ đối tượng nguồn sẽ ghi đè lên thuộc tính hiện có trong đối tượng đích.

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };

const result = Object.assign(obj1, obj2);

console.log(result);  // { a: 1, b: 3, c: 4 }

Trong ví dụ trên, giá trị của b trong obj12, nhưng nó đã bị ghi đè bởi giá trị 3 từ obj2.

Sao Chép Nông (Shallow Copy)

Object.assign() chỉ tạo ra sao chép nông (shallow copy), nghĩa là nó chỉ sao chép các thuộc tính từ đối tượng nguồn vào đối tượng đích ở tầng ngoài cùng. Nếu một thuộc tính là một đối tượng hoặc mảng lồng nhau, chỉ tham chiếu đến đối tượng đó được sao chép, không phải đối tượng thực sự.

Ví Dụ Về Sao Chép Nông

const obj = { a: 1, nested: { b: 2 } };
const copy = Object.assign({}, obj);

copy.nested.b = 3;

console.log(obj.nested.b);  // 3

Trong ví dụ này, đối tượng nested trong đối tượng sao chép vẫn tham chiếu đến cùng một đối tượng nested trong đối tượng gốc. Do đó, khi bạn thay đổi giá trị của nested.b trong bản sao, giá trị trong đối tượng gốc cũng bị thay đổi.

Sao Chép Sâu (Deep Copy)

Để thực hiện sao chép sâu (deep copy) các đối tượng lồng nhau, Object.assign() không phải là phương pháp thích hợp vì nó chỉ sao chép nông. Để sao chép sâu, bạn có thể sử dụng các thư viện như Lodash (_.cloneDeep()) hoặc tự viết hàm sao chép sâu.

Ví Dụ Về Sao Chép Sâu

Một ví dụ đơn giản về sao chép sâu bằng cách sử dụng JSON:

const obj = { a: 1, nested: { b: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));

deepCopy.nested.b = 3;

console.log(obj.nested.b);  // 2

Trong ví dụ này, JSON.stringify() chuyển đổi đối tượng thành chuỗi JSON, và JSON.parse() tạo ra một đối tượng mới từ chuỗi đó, đảm bảo sao chép sâu cho cả các đối tượng lồng nhau.

Xử Lý Các Thuộc Tính Không Liệt Kê

Các thuộc tính không liệt kê (non-enumerable properties) và các thuộc tính của đối tượng nguyên mẫu (prototype properties) không được sao chép bởi Object.assign(). Nó chỉ sao chép các thuộc tính có thể liệt kê (enumerable properties).

const obj = Object.create({ a: 1 }, { b: { value: 2, enumerable: false } });

const copy = Object.assign({}, obj);

console.log(copy);  // {}

Trong ví dụ này, thuộc tính b không được sao chép vì nó không có thuộc tính enumerable và thuộc tính a là thuộc tính của nguyên mẫu.

Xử Lý Với Các Giá Trị Null Hoặc Undefined

Nếu một đối tượng nguồn có giá trị là null hoặc undefined, Object.assign() sẽ bỏ qua đối tượng đó mà không gây ra lỗi.

const target = { a: 1 };
const source = null;

const result = Object.assign(target, source);

console.log(result);  // { a: 1 }

Phương thức Object.assign() bỏ qua đối tượng source khi nó là null.

Kết Luận

Object.assign() là một phương thức tiện dụng trong JavaScript để sao chép thuộc tính từ các đối tượng nguồn sang đối tượng đích, giúp hợp nhất và bổ sung các thuộc tính một cách dễ dàng. Tuy nhiên, cần lưu ý rằng phương thức này chỉ sao chép nông và không hỗ trợ sao chép sâu. Khi làm việc với các đối tượng lồng nhau hoặc cần sao chép sâu, bạn cần sử dụng các giải pháp khác như JSON.parse()JSON.stringify() hoặc các thư viện hỗ trợ như Lodash.

Tóm lại, Object.assign() mang lại sự tiện lợi khi thao tác với các đối tượng trong JavaScript, nhưng cần sử dụng một cách cẩn thận để tránh những lỗi không mong muốn liên quan đến tham chiếu đối tượng.