深刻探究JavaScript對象系列(三)

       爲了看着不是那麼累,本屌仍是決定寧願把本系列多寫幾篇,每篇控制在必定長度,也方便看官們閱讀。chrome

一.屬性特性

       上一篇中提到「屬性特性」這個概念,一個普通的數據屬性具備:可寫性、可枚舉性、可配置性,若是把它的值也當作特性的話,即一個普通的數據屬性就是:值(value)、可寫性(writable)、可枚舉性(enumerable)、可配置性(configurable);因爲存取器屬性沒有可寫性,所以存取器的特性能夠分爲:讀取、寫入、可枚舉性和可配置性。函數

       爲了實現屬性特性的查詢和操做,ECMAScript5中定義了一個名爲「屬性描述符」的對象,用來表明那4個特性,經過調用Object.getOwnPropertyDescriptor()方法能夠獲取某個對象特定屬性的屬性描述符,對於不存在的屬性和繼承屬性則返回undefined:測試

var o ={
    x : 2,
    y : 3,

    get z(){
        return this.x*this.y;
    },
    set z(value){
        this.x += value;
        this.y += value;
    }
};

Object.getOwnPropertyDescriptor(o,"x");      
//返回Object {value: 2, writable: true, enumerable: true, configurable: true}

Object.getOwnPropertyDescriptor(o,"r");
//返回Object {get: function, set: function, enumerable: true, configurable: true}

 

二.設置屬性特性

       經過Object.defineProperty()方法能夠設置屬性的特性,此函數須要傳入3個參數,第一個是要修改的對象,第二個是要修改或建立的屬性,第三個是屬性描述符對象,若是操做成功,則返回這個被修改後的對象,以下所示:this

 1 var  o = {};
 2 Object.defineProperty(o,"x",{
 3     value:1,
 4     writable:true,
 5     enumerable:false,
 6     configurable:true
 7 });
 8 
 9 console.log(o.x);    //返回1
10 Object.keys(o);   //返回[],x是不可遍歷的
11 
12 o.x = 3;
13 console.log(o.x);   //返回3 ,屬性是可寫的
14 
15 Object.defineProperty("x",{writable:false});
16 
17 o.x = 6; //操做失敗,說明x此時已是不可寫的

       當用該方法修改或新建屬性特性時,沒必要把所有4種屬性特性都寫出來,但對於新建立的屬性來講,默認的屬性特性值爲false或undefined,有一點要特別注意:該方法只能新建或修改自有屬性,不能操做繼承屬性。spa

       除了Object.defineProperty()之外,js還提供了一個Object.defineProperties()方法來批量操做屬性的特性,也是返回修改後的對象,以下:code

1 var p =Object.defineProperties({},{
2  x:{value:1, writable:false, enumerable:true, configurable:false},
3  y:{value:3, writable:true},
4  r:{get:function(){return this.x+this.y},
5     set:function(value){this.x+=value;this.y+=value;},
6     enumerable:true,
7     configurable:false
8    }
9 });

 

三.屬性特性的完整規則

       在《JavaScript權威指南》中,共列出了6條屬性特徵的規則,有點難記,感受仍是寫一字不漏的放在這當字典比較好,碰到具體問題時多看幾遍就記住了:對象

  • 若是對象是不可擴展的,則能夠編輯已有的自有屬性,但不能給它添加新屬性;
  • 若是屬性是不可配置的,則不能修改它的可配置性和可枚舉性;
  • 若是存取器屬性是不可配置的,則不能修改其getter和setter方法,也不能將它轉換爲數據屬性;
  • 若是數據屬性是不可配置的,則不能將它轉換爲存取器屬性;
  • 若是數據屬性是不可配置的,則不能將它的可寫性從false轉換爲true,可是能夠從true轉換爲false;(這條比較奇怪)
  • 若是數據屬性不可配置且不可寫的,則不能修改它的值。然而可配置但不可寫屬性的值是能夠修改的。

      寫到這裏,忽然間有個疑問,若是把一個屬性的特性修改成同時具備值特性和存取器屬性會怎麼樣,結果在chrome的測試結果爲失敗,提示ypeError: Invalid property. A property cannot both have accessors and be writable or have a value, #<Object>,因此有一樣疑問的人就不用瞎折騰了。blog

相關文章
相關標籤/搜索