深入探究JavaScript对象系列(三)

       为了看着不是那么累,本屌还是决定宁愿把本系列多写几篇,每篇控制在一定长度,也方便看官们阅读。

一.属性特性

       上一篇中提到“属性特性”这个概念,一个普通的数据属性具有:可写性、可枚举性、可配置性,如果把它的值也看成特性的话,即一个普通的数据属性就是:值(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个参数,第一个是要修改的对象,第二个是要修改或创建的属性,第三个是属性描述符对象,如果操作成功,则返回这个被修改后的对象,如下所示:

 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,有一点要特别注意:该方法只能新建或修改自有属性,不能操作继承属性。

       除了Object.defineProperty()以外,js还提供了一个Object.defineProperties()方法来批量操作属性的特性,也是返回修改后的对象,如下:

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>,所以有同样疑问的人就不用瞎折腾了。

posted @ 2013-12-23 21:58  山贼一名  阅读(353)  评论(0编辑  收藏  举报