深刻探究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

相关文章
相关标签/搜索