属性标志和属性描述符

属性标志

平时我们用的对象值,其实是一个属性的标志之一 value ,其他三个是:

  • writable 是否可写
  • enumerable 是否可遍历
  • configurable 是否可配置,表示属性是否可被删除,被修改。

使用常用对象字面量方式声明一个属性时,上面三个值默认都是 true

获取属性描述符

  • 获取单个:getOwnPropertyDescriptor(obj, propertyName)
  • 获取所有: getOwnPropertyDescriptors(obj)

注意:可获取Symbol属性
返回值如下:

  1. var obj = {name: 'John'}
  2. getOwnPropertyDescriptor(obj, 'name');
  3. {
  4. "value": "John",
  5. "writable": true,
  6. "enumerable": true,
  7. "configurable": true
  8. }

设置属性描述符

  • 设置单个:defineProperty(obj, propertyName, descriptor)
  • 设置多个: defineProperties(obj, {prop1: descriptor1, prop2: descriptor2})

注意:如果只设置value的话,其他属性描述符的值默认是 false ,而使用对象字面量等常规方式设置属性值,其他属性描述符默认是 true 。所以如果使用该方法设置属性,其他描述符的值需要设置指明,以防意外。

只读

设置 writablefalse 即可。
注意:再次对属性赋值,严格模式下会抛错,非严格模式下忽略

不可枚举

设置 enumerablefalse
注意:for inObject.keys 都无法获取到

不可配置

设置 configurablefalse
注意:该配置用途是防止更改和删除,但是可以修改 value 属性的值,前提是它是可 writable 的,如果本身已不是可写的,之后也无法从不可写改成可 writable 状态。

  1. // 实现一个常量
  2. let user = {name: 'John'}
  3. Object.defineProperty(user, 'name', {
  4. configurable: false,
  5. writable: false
  6. })
  7. // 无法修改描述符

强力克隆

for inObject.keys 无法遍历出 Symbol 属性。

  • 使用 ... 可以实现克隆 Symbol
  • 使用 Object.defineProperties({}, Object.getOwnPropertyDescriptor(obj))

    密封对象

    这些方法用的不是很多

    禁止添加新属性

    Object.preventExtensions(obj) ,对应检测方法 Object.isExtensible(obj)

    禁止添加/删除属性

    Object.seal(obj) ,相当于设置 configurable: false ,对应检测方法 Object.isSealed(obj)

    禁止添加/删除/修改属性值

    Object.freeze(obj) ,相当于 configurable:false writable: false ,对应检测方法 Object.isFrozen(obj)

属性的getter和setter

前文描述的都是数据属性,这里将描述的是 访问器属性,本质是用于获取和设置值的函数

Getter和Setter

对象字面量中,使用 get & set 来表示。

  1. let obj = {
  2. get name() {}, // 读取时使用
  3. set name() {} // 设置时使用
  4. }

访问器描述符

没有 value & writable 取而代之的时 get & set两者只能选其一,同时设置将报错。

  1. let obj = {}
  2. Object.defineProperty(obj, 'name', {
  3. get() {
  4. return ..
  5. },
  6. set(v) {
  7. this.x = v
  8. }
  9. })