理解属性描述对象

1.概述

JavaScript提供了一个内部数据结构,用来描述一个对象的属性的行为,控制它的行为。这被称为“属性描述对象”(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。

ECMAScript中属性特性又分为两种属性:数据属性和访问器属性。

(1)数据属性

用来描述一个对象的属性的行为,控制它的行为

1.可枚举性(enumerable): 
可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。 默认true

2.可配置性(configurable): 
可配置性(configurable)决定了是否可以修改属性描述对象。 默认true

3.可写性(writable):
可写性(writable)决定了属性的值(value)是否可以被改变。 默认true,Value 包含这个属性的数据值  默认值为undefined

(2)访问器属性(该属性的值不是实际存在的,而是每次读取时计算生成的)

除了直接定义以外,属性还可以用存取器(accessor)定义。其中,存值函数称为setter,使用set命令;取值函数称为getter,使用get命令。

var o = {
  get p() {
    return 'getter';
  },
  set p(value) {
    console.log('setter: ' + value);
  }
};


o.p // "getter"
o.p = 123 // "setter: 123"

2.使用Object()自身静态方法对其操作

(1)使用Object.getOwnPropertyDescriptor()读出对象自身属性的属性描述对象

var o = { p: 'a' };

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

(2)使用Object.defineProperty(),Object.defineProperties()定义或改写属性,然后返回修改的对象

语法:Object.defineProperty(object, propertyName, attributesObject)
第一个是属性所在的对象,第二个是属性名(它应该是一个字符串),第三个是属性的描述对象。

var o = Object.defineProperty({}, 'p', {//定义一个属性
  value: 123,
  writable: false,
  enumerable: true,
  configurable: false
});

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
  }
});

o.p1 // 123
o.p2 // "abc"
o.p3 // "123abc"

(3)使用Object.getOwnPropertyNames()方法返回直接定义在某个对象上面的全部属性的名称,不管该属性是否可枚举。

var o = Object.defineProperties({}, {
  p1: { value: 1, enumerable: true },
  p2: { value: 2, enumerable: false }
});

Object.getOwnPropertyNames(o)
// ["p1", "p2"]

(4)使用Object.prototype.propertyIsEnumerable()方法用来判断一个属性是否可枚举。

var o = {};
o.p = 123;

o.propertyIsEnumerable('p') // true
o.propertyIsEnumerable('toString') // false

用户自定义的p属性是可枚举的,而继承自原型对象的toString属性是不可枚举的。

下面是控制对象状态的一些方法

Object.preventExtensions():防止对象扩展。
Object.isExtensible():判断对象是否可扩展。
Object.seal():禁止对象配置。
Object.isSealed():判断一个对象是否可配置。
Object.freeze():冻结一个对象。
Object.isFrozen():判断一个对象是否被冻结。

链接:有关属性描述对象的更加详细内容看阮老师的属性描述对象一文。

原文地址:https://www.cnblogs.com/yf2196717/p/12843601.html