Fork me on GitHub

JavaScript对象的property属性详解及其Object.defineProperty方法

JavaScript中对象的property有三个属性:
1.writable。该property是否可写。
2.enumerable。当使用for/in语句时,该property是否会被枚举。
3.configurable。该property的属性是否可以修改,property是否可以删除。

在ECMAScript 3标准中,上面三个属性的值均为true且不可改:新建对象的property是可写的、可被枚举的、可删除的;而在ECMAScript 5标准中,可通过property的描述对象(property descriptor)来对这些属性进行配置和修改。

如果将property的值信息也作为property的属性来看的话,对象中的property拥有四个属性:value、writable、enumerable和configurable。

 

ECMAScript5.1(ECMA-262)中定义了标准属性Object.defineProperty 方法

ECMAScript 5标准中,可以通过Object.getOwnPropertyDescriptor()来获取对象自身某个property的属性信息:

1 var o = {x:1};
2 var a = Object.create(o);
3 a.y = 3;
4 console.log(Object.getOwnPropertyDescriptor(a, "y"));//Object {configurable=true, enumerable=true, writable=true, value=3}
5 console.log(Object.getOwnPropertyDescriptor(a, "x"));//undefined

可以看到,如果property不存在或者property继承自原型对象,则返回undefined。

 

ECMAScript 5标准中,可以通过Object.defineProperty()来设置对象自身某个property的属性:

Object.defineProperty(obj, prop, descriptor)

  • obj ,待修改的对象
  • prop ,带修改的属性名称
  • descriptor ,待修改属性的相关描述

descriptor 要求传入一个对象,其默认值如下,

/**
 * @{param} descriptor
 */

{
    configurable: false,
    enumerable: false,
    writable: false,
    value: null,
    set: undefined,
    get: undefined
}

  

  1. configurable ,属性是否可配置。可配置的含义包括:是否可以删除属性(delete ),是否可以修改属性的 writable 、 enumerable 、configurable 属性。
  2. enumerable ,属性是否可枚举。可枚举的含义包括:是否可以通过for...in 遍历到,是否可以通过 Object.keys() 方法获取属性名称。
  3. writable ,属性是否可重写。可重写的含义包括:是否可以对属性进行重新赋值。
  4. value ,属性的默认值。
  5. set ,属性的重写器(暂且这么叫)。一旦属性被重新赋值,此方法被自动调用。
  6. get ,属性的读取器(暂且这么叫)。一旦属性被访问读取,此方法被自动调用。

 

经过上述的示例,正常情况下 Object.definePropert() 的使用都是比较简单的。

不过还是有一点需要额外注意一下, Object.defineProperty() 方法设置属性时,属性不能同时声明访问器属性( set 和 get )和 writable 或者 value 属性。 意思就是,某个属性设置了 writable 或者 value 属性,那么这个属性就不能声明 get 和 set 了,反之亦然。

因为 Object.defineProperty() 在声明一个属性时,不允许同一个属性出现两种以上存取访问控制。

示例代码,

var o = {},
    myName = 'erik';

Object.defineProperty(o, 'name', {
    value: myName,
    set: function(name) {
        myName = name;
    },
    get: function() {
        return myName;
    }
});

  

上面的代码看起来貌似是没有什么问题,但是真正执行时会报错,报错如下,

TypeError: Invalid property.  A property cannot both have accessors and be writable or have a value, #<Object>

因为这里的 name 属性同时声明了 value 特性和 set 及 get 特性,这两者提供了两种对 name 属性的读写控制。这里如果不声明 value 特性,而是声明writable 特性,结果也是一样的,同样会报错。

posted @ 2016-01-18 17:57  donglegend  阅读(578)  评论(0编辑  收藏  举报