Object copy vs Array copy trong javascript giống câu chuyện vợ chồng!

Nội dung bài viết

Video học lập trình mỗi ngày

Hai khái niệm shallow copy và deep copy trong ngành lập trình thì có thể nghe đến ngán lỗ tai. Chính vì vậy nếu bạn nào còn nhớ thì cách đây 2 năm tôi cũng đã viết một số bài về 2 khái niệm này. Và bài viết này tôi sẽ thêm những phương án mới với những tính năng gần đây.

Shallow copy và deep copy

Trước tiên để hiểu shallow copy và deep copy là gì? Thì bạn không cần phải hiểu học thuật của nó. Cứ hiểu như tôi đây.

Shallow copy giống như hai vợ chồng xài chung một tài khoản vậy. Thẻ ATM được clone ra thành 2 thẻ ATM. Vợ or chồng nhận lương thì 2 thẻ đó được cộng thêm tiền (Vì chung tài khoản mà). Ông chồng đi nhậu, cà thẻ thì 2 thẻ đó cũng mất tiền luôn... Nên sinh ra cãi nhau, vì vậy mỗi người một thẻ cho chắc ăn.

Chính vì vậy mới có deep copy, vậy tiếp tục hiểu deep copy là gì?

deep copy là mỗi người một thẻ ATM, không ai đụng đến ai. Mỗi tài khoản đều có thuộc tính chung như số Hộ Khẩu... Nhưng biến động số dư thì của mỗi người. Khi thay đối số dư thi bên nào biết bên ấy. Gia đình hoà thuận yên ấm.

Bây giờ tôi sẽ thử nghiệm các phương án về hai khái niệm trên để cho các bạn cũng như tôi xem xét lại một lần nữa. Đương nhiên là bài viết trước đó vẫn còn giá trị, bạn có thể tham khảo lại.

Shallow copy array javascript

Đây là cách mà các bạn thường làm để copy Array với việc sử dụng Array.from() như sau, lấy gia đình làm ví dụ luôn:

/*
Với shk is sổ hộ khẩu, dkkh is đăng ký kết hôn, 3000 tiền VNĐ và 2000 là tiền $
*/
let atm = ['shk', 'dkkh', [3000, 2000] ];
// Use Array.from()
let atmVo = Array.from(atm);
let atmChong = Array.from(atm);
// Chong an nhau quet the 500 ngan
atmChong[2][1] = 2000 - 500;

console.log(atmChong); // ['shk', 'dkkh', [3000, 1500] ]
console.log(atmVo); // ['shk', 'dkkh', [3000, 1500] ]

Bạn có thể nhìn vào hình ảnh cho dễ, các bạn thấy đấy, khi chồng ăn nhậu mất 500K thì ATM của Vợ cũng bị trừ theo, Người ta gọi là giá trị tham chiếu đấy. Shallow copy array javascript


CÒn bây giờ chúng ta qua xem Shallow copy object xem thử có bị như vậy không?

Shallow copy object javascript

Tương tự như ví dụng trên nhưng chúng ta sử dụng Object.assign(), và chúng ta có kết quả gì đây.

let atm = {
    shk: '0123456789',
    dkkh: '888888',
    money: [3000, 2000]
}

// Use Object.assign()
let atmVo = Object.assign({}, atm);
let atmChong = Object.assign({}, atm);

// Chong an nhau quet the 500 ngan
atmChong.money[1] = 2000 - 500;

Kết quả cũng cho ta thấy tương tự nhau: Shallow copy array javascript


Qua hai ví dụ cho ta thấy nếu như không nhận ra sớm điều này thì quả thực nghiêm trọng, thay đổi dữ liệu hiện tại làm thay đổi dữ liệu GỐC quả là không tốt cho những người làm việc theo nhóm. Đương nhiên ở đây tôi chí lấy hai phương thức phổ biến nhanh gọn lẹ mà thôi đó là Object.assign() và Array.from(). Bạn có thể tìm hiểu nhiều cách sử dụng hơn khi sử dụng Object.assign() cũng như Array.from().

Deep copy array javascript

Trên mục đầu tiên cho ta thấy việc clone một array như vậy không chính xác, vậy phải làm cách nào. Có một số bài viết sử dụng JSON.stringify() để thực hiệu điều này. Bạn có thể tham khảo, nhưng nó thật sử không đúng. Vì những đối tượng như Date, Map, hay Set sẽ không được copy một cách chuẩn xác. Đọc bài viết về sử dụng JSON.stringify() bạn sẽ thấy nó sai.

Deep copy object javascript

Để giải quyết cho hai vấn đề đó là "Deep copy array javascript" và "Deep copy object javascript" thì chúng ta có thể sử dụng đệ quy để lấy ra và ghép vào từng item. Bây giờ tôi viết một function để deep clone có thể sử dụng cả object và Array luôn.

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj; 
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== "object") return obj;
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

Giờ chúng ta thử nghiệm lại như hai ví dụ trên. Tôi đã làm và chụp hình lại cho các bạn xem. Kết quả thật là mỹ mãn.

Deep copy object javascript


Và đây là kết quả của Deep copy array javascript Deep copy array javascript

Tóm lại

Thông qua bài viết này, những bạn mới học javascript để chuẩn bị cho quá trình tiến lên reactjs hay vuejs thì những khái niệm này cần nắm vững. Không cần phải nhớ nhiều, cứ nhớ câu chuyện của hai vợ chống là được. Muốn copy một object thì sử dụng Object.assign() còn nếu muốn copy một Array thì có thể sử dụng Array.from(). Ngoài ra có thể sử dụng nhiều cách, như concat(), hay spread syntax operator và còn nhiều cách khác. Nhưng để thực hiện Deep Clone thì bạn có thể sử dụng cách của tôi như trên.

Happy coding!!

Có thể bạn đã bị missing