属性描述对象

概述

js提供了一个内部结构,用来描述一个对象的属性的行为,这些被称为‘属性描述对象(attributes object)。每个属性都有自己对应的属性描述对象,保存改属性的一些元信息。

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

属性描述对象提供6个元属性。

(1)value

value存放该属性的属性值,默认为undefined。

(2)writable

writable存放一个布尔值,表示属性值(value)是否可改变,默认为true。

(3)enumerable

enumerable存放一个布尔值,表示该属性是否可枚举,默认为true。如果设为false,会使得某些操作(比如for...in循环、Object.keys())跳过该属性。

(4)configurable

configurable存放一个布尔值,表示“可配置性”,默认为true。如果设为false,将阻止某些操作改写该属性,比如,无法删除该属性,也不得改变该属性的属性描述对象(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。

(5)get

get存放一个函数,表示该属性的取值函数(getter),默认为undefined。

(6)set

set存放一个函数,表示该属性的存值函数(setter),默认为undefined。

getOwnPropertyDescriptor()

读出对象自身属性的属性描述对象。

var o = {p: 'a'}
Object.getOwnPropertyDescriptor(o, 'p')
// Object { value: "a",
//   writable: true,
//   enumerable: true,
//   configurable: true
// }

Object.defineProperty(),Object.defineProperties()

Object.defineProperty方法允许通过定义属性描述对象,来定义或修改一个属性,然后返回修改后的对象。

var o = Object.defineProperty({}, 'p', {
  value: 123,
  writable: false,
  enumerable: true,
  configurable: false
});

如果属性已经存在,Object.defineProperty方法相当于更新该属性的属性描述对象。

需要注意的是,Object.defineProperty方法和后面的Object.defineProperties方法,都有性能损耗,会拖慢执行速度,不宜大量使用。

如果一次性定义或修改多个属性,可以使用Object.defineProperties方法。

var o = Object.defineProperties({}, {
  p1: { value: 123, enumerable: true },
  p2: { value: 'abc', enumerable: true },
  p3: { get: function () { return this.p1 + this.p2 },
    enumerable:true,
    configurable:true
  }
});

一旦定义了取值函数get(或存值函数set),就不能将writable设为true,或者同时定义value属性,会报错。

Object.defineProperty()和Object.defineProperties()的第三个参数,是一个属性对象。它的writable、configurable、enumerable这三个属性的默认值都为false。

元属性

属性描述对象的属性,被称为“元属性”,因为它可以看作是控制属性的属性。

可枚举性(enumerable)

JavaScript的最初版本,in 运算符和基于它的for...in循环,会遍历对象实例的所有属性,包括继承的属性。
后来就引入了“可枚举性”这个概念,只有可枚举的属性,才会被for...in循环遍历,同时还规定原生继承的属性都是不可枚举的,这样就保证了for...in循环的可用性。

可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。具体来说,如果一个属性的enumerable为false,下面三个操作不会取到该属性。

for..in循环
Object.keys方法
JSON.stringify方法

基本上,JavaScript原生提供的属性都是不可枚举的,用户自定义的属性都是可枚举的。

与枚举性相关的几个操作的区别的是,for...in循环包括继承自原型对象的属性,Object.keys方法只返回对象本身的属性。如果需要获取对象自身的所有属性,不管是否可枚举,可以使用Object.getOwnPropertyNames方法,详见下文。

可配置性(configurable)

可配置性(configurable)决定了是否可以修改属性描述对象。也就是说,当configurable为false的时候,value、writable、enumerable和configurable都不能被修改了。

你可能感兴趣的:(属性描述对象)