在新的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能夠實現不少意想不到的功能,除了保持對象屬性不變,能夠監聽屬性變化、讀取(相似日誌),還能像內置對象的屬性同樣,擴展得方法也能不被枚舉出來。