How can I deep freeze an object in JavaScript?

Nội dung bài viết

Với một developer javascript (devjs) trong một thời gian làm việc thì sẽ biết được rằng object trong JavaScript là mutable. Bất kể bạn đã định nghĩa và khai báo chúng với const, nhưng điều đó không có nghĩa rằng object đó là immutable. Trước đây, chúng tôi có trình bày một tipjs đó là "Unison const và Object.freeze()".


Nhưng giờ đây điều đó không có nghĩa là sai nhưng, mỗi ngày devjs càng hoàn thiện những kỹ năng tối ưu code hay tự điều chỉnh code của mình cho phù hợp. Và chính trong bài viết này, thì chúng ta sẽ đi theo một giải pháp khác hiệu quả hơn những gì chúng ta thấy.

Notes: Cho phép tôi nói thêm điều này, thật ra theo quan điểm cá nhân tôi thì, những tips này thật sự là giá trị, vì nó sẽ giúp bạn hiểu được nhiều hơn về mutable, immutable trong javascript. mà đa số các bạn bỏ qua.

Để hiểu về mutable và immutable thì bạn có thể quay lại thời gian để đọc về bài viết trước về mutable và immutable. Còn chúng ta dành thời gian cho giải pháp tiếp theo.

Sử dụng const có thể giải quyết immutable trong object?

Quay lại vấn đề chính, thực tế khi ta dùng const thì có thể immutable được những một số tình huống. Tuy nhiên đối với Array, Object thì không thể. Bạn có thể xem ví dụ dưới đây:

#Example 1:

const myObj = { a: 10, b: 20, c: 30 };
myObj.a = 12;     // { a: 12, b: 20, c: 30 };

const myArr = [15, 25, 35];
myArr[1] = 28;    // [15, 28, 35];

Qua Example 1, bạn có thể thấy bạn đã định nghĩa bằng cách sử dụng const nhưng không thể như ý.

Sử dụng object.freeze() có thể giải quyết immutable trong object?

Thực tế, cũng còn nhiều trường hợp chúng ta cũng phải sử dụng object.freeze() để ngặn chặn những thay đổi trong object nhưng những nỗ lực của bạn cũng không đủ để làm tốt hơn mong đợi

#Example 2:

const myObj = {
  a: 1,
  b: 'hello',
  c: [0, 1, 2],
  d: { e: 1, f: 2 }
};
Object.freeze(myObj);

myObj.a = 10;
myObj.b = 'hi';
myObj.c[1] = 4;
myObj.d.e = 0;
/*
myObj = {
  a: 1,
  b: 'hello',
  c: [0, 4, 2],
  d: { e: 0, f: 2 }
}
*/

Nhìn vào Example 2, đối với Array và Object bạn không thể ngăn chặn dữ liệu bị thay đổi. Tuy nhiên, trong khi object.freeze() cung cấp phần nào giải pháp, nó chỉ giảm thiểu vấn đề đến mức lồng nhau tiếp theo, vì trong thực tế, nó thực hiện shallow freeze. Điều này có nghĩa là các thuộc tính là các đối tượng hoặc mảng vẫn có thể bị mutable:

Giải pháp giải quyết immutable trong object

Như bạn có thể thấy, object.freeze() là một bước đi đúng hướng, nhưng chỉ shallow freeze. Để giải quyết vấn đề, chúng ta có thể sử dụng đệ quy, kiểm tra xem mỗi thuộc tính có phải là một đối tượng không và nếu Object.isFrozen() return false, hãy áp dụng object.freeze() cho nó:

Tipjs: Deep copy Object, Array, Function Javascript # Example 3:

const myObj = {
  a: 1,
  b: 'hello',
  c: [0, 1, 2],
  d: { e: 1, f: 2 }
};

const deepFreeze = obj => {
  Object.keys(obj).forEach(prop => {
    if (obj[prop] === 'object' && !Object.isFrozen(obj[prop])) deepFreeze(v[prop]);
  });
  return Object.freeze(obj);
};
deepFreeze(myObj);

myObj.a = 10;
myObj.b = 'hi';
myObj.c[1] = 4;
myObj.d.e = 0;

/*
myObj = {
  a: 1,
  b: 'hello',
  c: [0, 1, 2],
  d: { e: 1, f: 2 }
}
*/

Trong ví dụ trên, chúng tôi áp dụng các kỹ thuật mà chúng tôi đã mô tả trước đây để đảm bảo rằng đối tượng đã cho object deeply frozen. Bạn có thể xem  hoàn chỉnh ở đây , cùng với nhiều ví dụ khác trong đoạn trích DeepFreeze.

Ref: 30secondsofcode

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