javascript存儲器屬性與數據屬性

在新的js規範中,咱們又多了幾種定義屬性的方法。給一個對象添加屬性,之前多是這樣的函數

var o = {name: '未起名';}

如今能夠這樣子this

var o = {get name(){return '終生不更名'}}

o.name // 終生不更名

o.name = '換個名字';

o.name // 終生不更名;無法改變其值

還能夠是這樣子的spa

var o = {};
Object.defineProperty(o, name, {
    value: '數據屬性',
    writable: true
})
// witable表示該屬性是否可讀寫。false只可讀,true可讀寫
o.name = '可修改的屬性'

o.name // ?

固然還有其餘的方式。日誌

以上兩種新的寫法,第一種添加的屬性叫作存儲器屬性(getter&setter),第二種是數據屬性(value)。一個【屬性描述符】不能同時包含value屬性又有setter&getter之一。code

【屬性描述符】是一個對象,它是描述對象屬性的。描述符通常有四個屬性,分爲存儲器屬性描述符和數據屬性描述符(這個是我本身的分類)對象

//存儲器屬性描述符對象
{
    get: function(){},
    set:function(){},
    enumerable:boolean,
    configurable:boolean
}

//數據屬性描述符對象
{
    value:'',
    writable:boolean,
    enumerable:boolean,
    configurable:boolean
}

若是沒有顯式聲明某屬性,默認是undefined或者false。enumerable表示該屬性是否可枚舉。像不少內置的對象的屬性同樣,設爲false,則此屬性是不能夠枚舉的(for in循環沒法遍blog

歷)。configurable表示是否可配置,如是否能夠用delete刪除此屬性,是否能夠修改enumerable或者writable的值。writable是否可寫,對於存儲器屬性,沒有該項。其讀寫操做由get、遞歸

set完成。固然,這只是粗略的說明。ip

存儲器屬性get

var name = '給孩子起個名吧',

person = {
    // 讀取屬性
    get childName(){
        return name;
    },
    // 給屬性寫入值
    set childName(newName){
        name = newName;
    },
    // 是否可枚舉
    enumerable: true,
   // 是否可配置
    configurable: true
}
// 上面這幾行代碼近似於下面的效果

/*
var person = {childName: name};
*/
/*這種寫法須要藉助第三個變量或者屬性來完成。由於在get和set使用【this.該屬性】會形成無限遞歸,沒法在set中沒法給
該屬性賦值,也沒法在get中返回。要麼藉助第三者(get&set),要麼返回常量(get)
*/
//一個能夠讀取,但不容許改變的值.例如產品的ID號,一旦生產,則不容許再修改
var product = {get pID(){return '113230'}}
product.pID = '231234' //1.0。企圖改變pID的值是徒勞的

 數據屬性

/* 數據屬性不能像存儲器屬性那樣直接在對象內部聲明,否則會變成普通屬性。
須要藉助defineProperty來完成*/
var o = {};
//defineProperty接受三個參數,對象,對象的屬性名,屬性描述符(也是對象)
Object.defineProperty(o,'name',{
    value: '這是數據屬性',//這個值也能夠是個函數,調用:o.name()
    writable: true,
    enumerable: true,
    configurable: true
});

o.name // 這是數據屬性

//存儲器屬性也能夠用這種方式(添加多個屬性用defineProperties),給一個矩形rect添加三個屬性,w,h,area

var rect = {};
Object.defineProperties(rect, {
    w:{value:10,writable:true},
h:{value:15,writable:true},
area: {
get: function(){
return this.w*this.h;
},
set: function(newVal){
var rat = newVal/this.area;
this.w *= rat;
this.h *= rat;
}
}
});
rect.area // 150
rect.area *= 2;
//改變面積的值,間接改變長和寬
rect.w // 20
rect.h // 30

總結:利用這些API能夠實現不少意想不到的功能,除了保持對象屬性不變,能夠監聽屬性變化、讀取(相似日誌),還能像內置對象的屬性同樣,擴展得方法也能不被枚舉出來。

更多相關閱讀或者這裏

相關文章
相關標籤/搜索