Property flags và descriptors là gì – Bí ẩn bên trong Javascript Object
Như chúng ta biết thì Object lưu trữ các thuộc tính, các thuộc tính chỉ đơn giản là các cặp “key-value”. Nhưng ngoài ra thì object còn chứa nhiều điều hay ho phía sau.
🥇 Property flags – các cờ thuộc tính
Thuộc tính object, bên cạnh một value
còn có một số thuộc tính đặc biệt (gọi là các cờ):
writable
– nếu true, giá trị có thể thay đổi, còn không thì chỉ đọc (read-only )enumerable
– nếu true, thì thuộc tính được liệt kê khi lặp, còn không thì không được liệt kêconfigurable
– nếu true, thuộc tính có thể bị xóa,writable
vàenumerable
có thể bị thay đổi, còn không thì không thể
Một thuộc tính sẽ có đầy đủ 3 cờ, người ta gọi 3 cờ của thuộc tính là bộ mô tả thuộc tính (property descriptor)
Phương thức Object.getOwnPropertyDescriptor
cho phép chúng ta lấy đầy đủ thông tin về thuộc tính
Để thay đổi cờ, chúng ta có thể sử dụng Object.defineProperty
descriptor
: Một object miêu tả các thuộc tính, nếu không cung cấp thì mặc định là false
🥇 Non-writable – Không thể thay đổi
Cùng làm user.name
không thể bị assign lại bằng cách thay đổi cờ writable
sang false
Lưu ý: Nếu không trong chế độ strict-mode thì sẽ không xảy ra lỗi, nhưng quá trình trên sẽ không thực hiện thành công
Đây là ví dụ thay đổi cờ writable
ngay từ lúc tạo
🥇 Non-enumerable – Không thể liệt kê
Cùng custom toString
của user
Bây giờ chúng ta không thích toString
xuất hiện khi trong vòng lặp, ta có thể set enumerable:false
Và đó cũng là lý do khi ta log một object thì ta nhận thấy một số thuộc tính bị làm mờ
Non-enumerable bị làm mờ
non-enumerable cũng có hiệu lực trong Object.keys
🥇 Non-configurable – Không thể cấu hình
Ý tưởng của configurable: false
là để ngăn chặn thay đổi cờ thuộc tính và xóa thuộc tính, trong khi đó bạn vẫn có thể thay đổi value của thuộc tính Cờ non-configurable (configurable:false
) thỉnh thoảng được set mặc định trong các Object xây dựng sẵn. Ví dụ Math.PI
thì non-writable, non-enumerable, non-configurable
Vì thế chúng ta không thể thay đổi giá trị của Math.PI
hoặc viết lại nó
Một khi chúng ta set một thuộc tính là non-configurable (configurable:false
) thì chúng ta không thể thay đổi lại bằng defineProperty
Khi configurable: false
thì chúng ta sẽ bị một số hạn chế trên defineProperty
- Không thể thay đổi cờ
configurable
- Không thể thay đổi cờ
enumerable
- Không thể thay đổi
writable: false
sangtrue
(ngược lại thì ok) - Không thể thay đổi
getter/setter
Đây là user.name
non-configurable, nhưng chúng ta còn có thể thay đổi (vì nó writable)
Và bây giờ chúng ta làm cho user.name
mãi mãi bị “niêm phong”
🥇 Object.defineProperties
Object.defineProperties(obj, descriptors) cho phép chúng ta định nghĩa nhiều thuộc tính cùng 1 lúc
Cú pháp:
Ví dụ
🥇 Object.getOwnPropertyDescriptors
Để lấy tất cả property descriptor cùng một lần, chúng ta có thể sử dụng Object.getOwnPropertyDescriptors(obj)
Kết hợp với Object.defineProperties
nó có thể được sử dụng như một cách để clone một object
Bình thường khi clone một object, chúng ta thường copy thuộc tính như thế này
Nhưng điều này không copy cờ. Vì thế nếu muốn một cách clone tốt hơn thì Object.defineProperties
là một sự lựa chọn tối ưu. Một sự khác biệt khác là for...in
bỏ qua các thuộc tính tượng trưng, nhưng Object.getOwnPropertyDescriptors
sẽ return về tất cả property descriptors bao gồm loại tượng trưng.
🥇 Sealing an object globally – Niêm phong một object toàn bộ
-
Object.preventExtensions(obj) Ngăn cấm thêm thuộc tính mới vào object
-
Object.seal(obj) Ngăn cấm thêm/xóa các thuộc tính. Set
configurable: false
cho tất cả thuộc tính đang tồn tại -
Object.freeze(obj) Ngăn cấm thêm/xóa/thay đổi các thuộc tính. Set
configurable: false, writable: false
cho tất cả các thuộc tính đang tồn tại -
Object.isExtensible(obj) Return
false
nếu việc thêm thuộc tính bị cấm, còn không thìtrue
. -
Object.isSealed(obj) Return
true
nếu thêm/xóa thuộc tính bị cấm, và tất cả thuộc tính tồn tại cóconfigurable: false
-
Object.isFrozen(obj) Return
true
nếu thêm/xóa/sửa thuộc tính bị cấm, và tất cả thuộc tính hiện tại làconfigurable: false, writable: false
Những phương thức này thì hiếm khi được sử dụng trong thực tế
🥇 Tham khảo
Bài viết được dịch từ
https://javascript.info/property-descriptors
Nguồn bài viết: https://duthanhduoc.com