2017-04-19 63 views
1

JavaScript對象可以被封閉,這樣可以防止添加新屬性並刪除或重新配置現有屬性,但屬性仍可寫。他們也可以被凍結,這是密封加上所有屬性變得不可寫。不允許更改現有屬性的可擴展對象?

顯着缺乏的是能夠使現有屬性爲只讀,不可移動,不可配置,同時使對象可擴展。這將有助於防止意外踐踏對象的屬性,同時允許其他代碼擴充其屬性。

使用vanilla JavaScript創建這樣一個對象的最佳或慣用方法是什麼?

回答

1

只需通過對象的屬性循環,使每一個不可寫和不可配置:

var obj = { "foo": 1, "bar": 3 }; 
Object.defineProperty(obj, "baz", { set: a=>a }); 

Object.getOwnPropertyNames(obj).forEach(function(name) { 
    var desc = Object.getOwnPropertyDescriptor(obj, name); 
    desc.configurable = false; 

    // make the property non-writable if it is not an accessor property 
    if(!desc.set && !desc.get) { desc.writable = false; } 

    Object.defineProperty(obj, name, desc); 
}); 

注意,這不會使存取器屬性由setget方法「不可寫」,因爲定義可寫性的概念不適用於訪問者屬性 - 存儲到訪問者屬性中運行該設置者。

+0

如果沒有提及,Firefox似乎只會留下「價值」。 – Pointy

+0

@FelixKling是的,我最近了解到'defineProperty'具有定義新屬性與修改現有屬性的不同行爲。儘管現在你已經提到了它,但是我應該添加一個'try' /'catch'來處理一些奇怪的情況 - 顯然現有的'set'插槽和'configurable:false'在嘗試執行'configure:虛假「。 – apsillers

+0

是啊,注意到現在......我總是被'defineProperty'這個名字弄糊塗了,因爲對我來說它表示創建了一個全新的屬性(吹掉了所有存在的東西)。 –

1

例如,你可以使用一個getter來設置你的屬性,如:

var object = {get property(){return "value"} }; 

使他們只讀的,這意味着你不能改變由分配它的價值了,因爲在:

object.property = "other"; 

因爲它沒有固定器。因此object.property將繼續返回「值」,但仍可以使用delete運算符刪除「屬性」鍵。

+0

這仍然允許該屬性被'Object.defineProperty'覆蓋。 –

+1

你不必一路走下去用這個尷尬的Object.definePropertty語法來做到這一點 - (因爲正如已經提到的那樣,你可以很容易地刪除它並指定一個新的)但如果你希望你的屬性安全地被意外地分配一個不同的值 - 比給定的語法將會做得更好。 –

相關問題