JS對象的數據屬性,訪問器屬性,防篡改對象

JS對象的數據屬性,訪問器屬性,防篡改對象

1. 數據屬性

高程是這樣定義數據屬性的:數據屬性包含一個數據值的位置。在這個位置能夠讀取和寫入值,數據屬性有四個描述其行爲的特性。(第三版6.1.1節,P139)測試

這裏引用高程上的詳細解釋(第三版6.1.1節,P139)this

[[Configurable]]:表示可否經過delete刪除屬性從而從新定義屬性,可否修改屬性的特性,或者可否把屬性修改成訪問器屬性。對於直接在對象上定義的屬性,它們的這個特性默認爲true

[[Enumerable]]:表示可否經過for-in循環返回屬性。對於直接在對象上定義的屬性,這個特性默認值爲true

[[Writable]]:表示可否修改屬性的值。對於直接在對象上定義的屬性,他們的這個特性默認爲true

[[Value]]:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀,寫入屬性值的時候,新值保存在這個位置。這個特性默認爲undefined

當修改configurable屬性爲false的時候,則該屬性被認爲是不可配置的,而且沒有屬性能夠被改變(除了單項修改writable爲false);

Q1:如今存在一個問題,若是修改configurable屬性爲false,那麼根據解釋,只能單向修改writable爲false,那麼若是writable爲true,可否改變屬性的值?spa

根據高程上的描述,值也算一個特性,理論上值不能被修改,可是實際上值是能夠被修改的,你們看下面的例子:code

var a = {b:'aa',c:'dd'};
a.b = 'cc';

Object.defineProperty(a,'b',{
    configurable:false
});

Object.defineProperty(a,'b',{
    value:'dd'
});
console.log(a); //{ b: 'dd', c: 'dd' }

a.b = 'ee';
console.log(a); //{ b: 'ee', c: 'dd' }

可是若是將wirtable修改成false就不能被修改值了,以下例子(接着上邊)對象

Object.defineProperty(a,'b',{
    writable:false
});
a.b = 'ff';

console.log(a); //{ b: 'ee', c: 'dd' }

因此能夠這麼理解,configurable屬性是控制configurable屬性自己、enumerable和writable這三個特性的。 而writable是控制value這個特性的,將configurable設置爲false並不影響value的可改變性,value是否可改變只與writable有關。ip

2. 訪問器屬性

四個:ci

[[configurable]]
[[Enumberable]]
[[get]]
[[set]]

高程上的解釋和詳細定義就不贅述了。get

有一點須要解釋一下,根據高程的上的一個例子,我作了一個相似的例子it

var book = {
    _year:2004,
    edition:1
};

Object.defineProperty(book,'year',{
    get:function () {
        return this._year;
    },
    set:function (v) {
        this._year = v+1;
    }
});

console.log(book._year); //能夠直接訪問以_year開頭的屬性,事實上這個和普通屬性沒什麼區別!
console.log(book.year);
book.year = 2332;
console.log(book.year);

高程上解釋:以_開頭的屬性是訪問器屬性,事實上沒有語法的規定,但這是約定俗成的;雖然能夠直接訪問以_開頭的屬性,可是做爲這個模塊的使用者,應該只是訪問同名的不帶_的屬性;做爲這個模塊的編寫者,應該編寫一個同名的不帶_的屬性做爲訪問器。好比year就是_year屬性的訪問器。io

Q2:還有一個問題,若是在設置屬性的時候同時指定訪問器屬性和數據屬性會發生什麼?

測試了一下,會報錯:

Object.defineProperty(book,'year',{
    get:function () {
        return this._year;
    },
    set:function (v) {
        this._year = v+1;
    },
    value:'22'
}); //TypeError: Invalid property descriptor. Cannot both specify accessors(構造器) and a value or writable attribute, #<Object>

最後,一旦將configurable指定爲false,4個訪問器屬性都沒法再修改了。

2.1 讀取屬性的特性

利用Object.getOwnPropertyDescriptor(object,object.name)來返回一個爲object.name量身定作的描述符對象。含有該屬性的特性信息。

3. 防篡改對象

有三種不一樣程度的防篡改級別

  1. 不可擴展:Object.preventExtensions(object)
  2. 密封:Object.seal(object)
  3. 凍結:Object.freeze(object)

用一張表能夠解釋防篡改的程度

添加新的屬性/方法   configurable    writable
不可擴展           ×                  √             √
密封              ×                  ×             √
凍結              ×                  ×             ×

檢測是否不可擴展:Object.isExtensiable(object) 檢測是否密封: Object.isSealed(object) 檢測是否凍結: Object.isFrozen(object)

相關文章
相關標籤/搜索