Day22 | 物件方法介紹 - 針對物件本身操作的方法
❒ 前言
上篇提到的 Object.defineProperty、Object.defineProperties 為調整物件本身的的屬性特徵方法,這篇將説說 preventExtensions ( 防止擴充 )、seal ( 封裝 )、Freeze ( 凍結 ) 這三種針對物件本身做限制的方法。
❒ 對物件本身調整的方法
- preventExtensions ( 防止擴充 )
- seal ( 封裝 )
- Freeze ( 凍結 )
preventExtension、seal、freeze 的共同點與差異
- 這三種方式都只能對物件本身做限制,無法對物件本身的巢狀屬性做限制。因為這三種方式只有淺層拷貝,物件本身的巢狀屬性就還是具有傳參考特性。
preventExtension可以調整屬性特徵,seal、freeze不能調整屬性特徵。- 備註:
seal屬性特徵中writable經測試是可以被調整的,似乎是seal有調整過導致,須留意。
- 備註:
- 限制程度:
freeze>seal>preventExtension
❒ preventExtension 防止擴充
特性: 不能「 新增 」物件本身屬性。
結構:Object.preventExtensions(物件)
Others :
Object.preventExtensions(物件)可搭配Object.isExtensible(物件)做驗證看使用了preventExtensions後的物件是否可被擴充。Object.preventExtensions(物件)可搭Object.getOwnPropertyDescriptor(物件, '屬性')查看物件裡的特定屬性特徵。物件使用
preventExtensions後的屬性特徵 ( 可使用Object.getOwnPropertyDescriptor(物件, '物件屬性');查詢 )1
2
3
4configurable: true,
enumerable: true,
value: 屬性本身的值
writable: true
範例 1. 使用 preventExtensions 物件屬性特徵不會被改變
1 | var person = { |
Object.isExtensible(person)印出false,可見preventExtensions的物件是不可被擴充的。- 以物件
a屬性為例,Object.getOwnPropertyDescriptor(person, 'a')可見a屬性的特徵們一樣為預設。

範例 2. 只能針對物件本身做限制,無法對巢狀屬性做限制
1 | var person = { |
- 調整物件原有屬性:把物件內的
a屬性的屬性值調整為a是沒問題的。 - 於物件新增屬性:物件新增
d屬性後,並沒有在物件中看見新增的d屬性,因為preventExtensions的用意就是無法新增屬性。 - 調整物件內的巢狀屬性:
preventExtensions只能對物件本身做限制,無法對物件本身的巢狀屬性做限制,所以在巢狀屬性c內再新增inC屬性是沒問題的。 - 調整物件屬性特徵:調整 a 的屬性特徵為
configurable: false,是沒問題的,可見preventExtensions是可以再次調整屬性特徵。
❒ seal 封裝
seal 特性
物件屬性「無法新增刪除」,也無法重新配置特徵,但是可以調整目前屬性值。
- 例外:
seal屬性特徵中writable經測試是可以被調整的,似乎是seal有調整過導致,須留意。
- 例外:
seal與preventExtensions是有關聯性的,所以seal預設狀態為物件會被加上preventExtensions,再把 「無法新增刪除,也無法重新配置特徵 」的特性加上。物件使用 seal 後的屬性特徵為 ( 可使用
Object.getOwnPropertyDescriptor(物件, '物件屬性');查詢 )1
2
3
4configurable: false,
enumerable: true,
value: 屬性本身的值
writable: true
seal 結構
Object.seal(物件);
範例 1
1 | var person = { |
- 調整物件原有屬性:把物件內的
a屬性的屬性值調整為a是沒問題的。 - 於物件新增屬性:物件新增
d屬性後,並沒有在物件中看見新增的d屬性,因為preventExtensions的用意就是無法新增屬性。 - 調整物件內的巢狀屬性:
preventExtensions只能對物件本身做限制,無法對物件本身的巢狀屬性做限制,所以在巢狀屬性c內再新增inC屬性是沒問題的。

範例 2. seal 封裝後是不能調整屬性特徵,但 writable 特徵例外
1 | var person = { |
writable 特徵例外:
修改了物件
a的屬性特徵writable由true變false,並使用Object.getOwnPropertyDescriptor查看封裝後物件的屬性特徵,開發者工具依舊顯示writable: false,驗證「 seal 封裝後的物件是無法調整屬性特徵 」。


調整其他特徵:
- 試圖改變其他特徵,會顯示錯誤訊息
Uncaught TypeError。

❒ freeze 凍結
特性
物件使用
freeze會讓此物件被凍結並且,- 無法新增刪除屬性。
- 無法被修改屬性值。
- 無法調整屬性特徵。
物件使用
freeze的屬性特徵 ( 可使用Object.getOwnPropertyDescriptor(物件, '物件屬性');查詢 )1
2
3
4configurable: false,
enumerable: true,
value: 屬性本身的值
writable: falsefreeze與seal和preventExtensions是有關聯性的,所以freeze預設狀態為物件會被加上preventExtensions( 無法被擴展 ) 和seal( 封裝 ) 的特性,也無法被調整值。
結構
Object.freeze(物件);
範例 1. freeze 具備無法被擴展、封裝、凍結特性
1 | var person = { |
範例 2. 物件 freeze 後嘗試調整、新增屬性與調整巢狀屬性
1 | var person = { |
- 調整屬性與新增屬性:失敗。
- 調整巢狀屬性:成功。
- 因為物件傳參考特性外加淺層拷貝,所以
freeze只能針對當下物件凍結,無法對物件屬性的巢狀屬性做凍結。
- 因為物件傳參考特性外加淺層拷貝,所以
範例 3. 物件凍結後嘗試調整屬性特徵
1 | var person = { |
- 此範例以調整 writable 特徵為例,會出現錯誤訊息
Uncaught TypeError。 - 另外嘗試調整其他屬性特徵 (
configurable、enumerable、value),一樣會跳出錯誤訊息。
參考資訊
- JavaScript 核心篇