Đối tượng bất biến trong Javascript

Thông thường, object trong JavaScript là mutable - nghĩa là trạng thái của object có thể thay đổi được. Nói cách khác là giá trị các thuộc tính trong Object có thể thay đổi được, ví dụ:

let obj = {}; // khởi tạo object rỗng

obj.a = 1; // thêm thuộc tính a và gán giá trị 1
obj["a"] = 2; // cập nhật giá trị thuộc tính a bằng 2

console.log(obj.a); // 2

Có nhiều trường hợp bạn muốn object đó là immutable - trạng thái không thể thay đổi được. Sau đây, mình sẽ giới thiệu với bạn 2 cách tạo immutable object trong JavaScript.

Tạo immutable object sử dụng Object.defineProperty

Object.defineProperty() định nghĩa một thuộc tính mới hoặc cập nhật thuộc tính có sẵn trên object.

Cách sử dụng Object.defineProperty

Để tạo immutable object sử dụng Object.defineProperty, bạn chỉ cần định nghĩa property với thuộc tính writable (có thể ghi đè) là false, ví dụ:

let obj = {};

    // định nghĩa thuộc tính a trong obj
    Object.defineProperty(obj, "a", {
      value: 1, // giá trị là 1
      writable: false, // writable: false - nghĩa là không thể ghi đè});

    obj.a = 2; // thử ghi đè giá trị khác vào a
    console.log(obj.a); // 1 - kết quả giá trị của a vẫn không đổi

Bạn thấy rằng giá trị của obj.a không thay đổi so với giá trị ban đầu, vẫn là 1. Đó chính là tính bất biến.

Nếu sử dụng ở strict mode thì đoạn code trên sẽ sinh ra lỗi:

"use strict";
let obj = {};

// định nghĩa thuộc tính a trong obj
Object.defineProperty(obj, "a", {
  value: 1, // giá trị là 1
  writable: false, // writable: false - nghĩa là không thể ghi đè
});

obj.a = 2;
// Uncaught TypeError:// Cannot assign to read only property 'a' of object '#<Object>'
console.log(obj.a);

Đúng vậy, nếu writable bằng false thì thuộc tính gọi là read only (thuộc tính chỉ đọc).

Thực tế, giá trị mặc định của thuộc tính writablefalse, nên bạn có thể bỏ qua thuộc tính này:

let obj = {};
Object.defineProperty(obj, "a", { value: 1 });
obj.a = 2;
console.log(obj.a); // 1

Thay đổi giá trị writable với Object.defineProperty

Câu hỏi đặt ra là: nếu mình muốn thay đổi giá trị của writable từ false thành true có được không?

Câu trả lời: mặc định là KHÔNG.

Khi định nghĩa thuộc tính bằng Object.defineProperty, ngoài writable ra thì còn có configurable (có thể chỉnh sửa).

Mặc định, giá trị của configurablefalse, nên đoạn code sau sẽ bị lỗi: TypeError: Cannot redefine property: a (không thể định nghĩa lại thuộc tính a).

let obj = {};
Object.defineProperty(obj, "a", { value: 1, writable: false });
Object.defineProperty(obj, "a", { writable: true }); // => TypeError: Cannot redefine property: a

Để giải quyết vấn đề này, bạn phải sửa configurable thành true:

let obj = {};

Object.defineProperty(obj, "a", {
  value: 1,
  writable: false,
  configurable: true,
});

Object.defineProperty(obj, "a", { writable: true });
obj.a = 2;
console.log(obj.a); // 2 - giá trị của thuộc tính a đã thay đổi

Nghĩa là bạn có thể biến immutable object thành mutable object được bằng cách này.

Tạo immutable object sử dụng Object.freeze

Phương thức Object.freeze() làm cho object không thể thay đổi, bao gồm:

  • Không thể thêm thuộc tính mới vào object.
  • Thuộc tính đã có thì không thể cập nhậtkhông thể bị xoá bỏ.

Object.freeze() có thể dịch ra là "đóng băng object".

Cách sử dụng Object.freeze

Ví dụ sử dụng Object.freeze() để tạo immutable object:

let obj = { a: 1 };

Object.freeze(obj); // đóng băng object
obj.a = 2; // cập nhật thuộc tính đã có
obj.b = 3; // thêm thuộc tính mới

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

Bạn thấy rằng obj vẫn không hề thay đổi.

Nếu sử dụng ở strict mode thì đoạn code sau sẽ bị lỗi:

"use strict";
let obj = { a: 1 };

Object.freeze(obj); // đóng băng object

obj.a = 2;
// Uncaught TypeError:
// Cannot assign to read only property 'a' of object '#<Object>'

Vì khi sử dụng Object.freeze(), tất cả các thuộc tính trong object đều trở thành read-only.

Cách để unfreeze object

Tương tự như câu hỏi ở trên.

Nếu mình muốn unfreeze object, để biến immutable object thành mutable object thì có được không?

Câu trả lời là KHÔNG.

Bạn không thể unfreeze object một khi nó đã freeze.

Tổng kết

Trên đây là 2 cách tạo immutable object trong JavaScript.

  • Sử dụng Object.defineProperty bằng cách set writable thành false.
  • Sử dụng Object.freeze.

Mỗi cách đều có những ưu, nhược điểm riêng. Tuỳ vào từng yêu cầu cụ thể mà bạn lựa chọn cách làm hợp lý.

Liên quan đến chủ đề immutable object, có một bài viết khá hay mà bạn có thể tham khảo thêm: Tuyệt chiêu đảm bảo tính bất biến trong JavaScript.

Bài trước
left Bài trước
left Khởi tạo đối tượng với từ khóa new trong javascript có tác dụng gì
Bài tiếp theo
Optional chaining trong Javascript right
Bài tiếp theo right
Avatar Techmely Team
VIẾT BỞI

Techmely Team