Object.defineproperty

339 阅读4分钟

Object.defineProperty()

Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

语法

object.defineProperty(obj, prop, descriptor)

参数

obj

要定义属性的对象

prop

要定义或修改的属性的名称

descriptor

要定义或修改的属性描述符

返回值

被传递给函数的对象

描述

该方法允许精确地添加或者修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到(for...inObject.keys()),可以改变这些属性的值,也可以删除这些属性。这个方法允许修改默认的额外选项。默认情况下,使用Object.defineProperty()添加的属性是不可修改(immutable)的

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,改值是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。

这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用Object.defineProperty())定义属性时的默认值:

  • configurable 当且仅当该属性的configurable健值为true时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除

    默认为false

  • enumerable 当且仅当该属性的enumerable键值为true时,该属性才会出现在对象的枚举属性中,

    默认为false

    数据描述符还具有以下可选键值

  • value 该属性对应的值。可以是任何有效的 JavaScript 值

    默认为undefined

  • writable 当且仅当该属性的writable键值为true时,属性的值,也就是上面的value,才能被改变

    默认为false 存取描述符还具有以下可选键值:

  • get 属性的 getter 函数,如果没有 getter,则为undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入this对象。该函数的返回值会被用作属性的值。

    默认为undefined

  • set 属性的 setter 函数,如果没有 setter,则为undefined。当属性值被修改时,会调用此函数。该方法接受一个参数,会被传入赋值时的 this 对象。

示例

创建属性

如果对象中不存在指定的属性,object.defineProperty()回去创建这个属性。当描述符中省略某些字段时,这些字段将使用他们的默认值。

// 创建一个新对象
const o = {}
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, 'a', {
    value: 37,
    writable: true,
    enumerable: true,
    configurable: true
})
// 对象 o 拥有了属性 a,值为 37

//在对象中添加一个设置了存取描述符属性的示例
const bValue = 38
Object.defineProperty(o, 'b', {
    get() { return bValue },
    set(newValue) { bValue = newValue },
    enumerable: true,
    configurable: true
})

修改属性

如果属性已经存在,Object.defineProperty()将尝试根据属性描述符中的值以及对象当前的配置来修改这个属性。如果旧描述符讲其configurable属性设置为false,则该属性被认为是"不可配置的",并且没有属性可以被改变(除了单向改变 writable 为 false)。当属性不可配置时,不能在数据和访问器属性类型之间切换。

当试图改变不可配置属性(除了 valuewritable 属性之外)的值时,会抛出 TypeError,除非当前值和新值相同。

  • Writable 属性writable属性设置为false时,该属性被称为不可写的。它不能被重新赋值。
const o = {}
Object.defineProperty(0, 'a', {
    value: 37,
    writable: false
})
console.log(o.a) // logs 37
o.a = 25
console.log(o.a) // logs 37. The assigment didn't work.
  • Enumerable 属性 enumerable 定义了对象的属性是否可以在for...in循环和Object.keys()中被枚举
  • Configurable 属性 configuration 特性表示对象的属性是否可以被删除,以及除 valuewritable 特性外的其他特性是否可以被修改
const o = {}

Object.defineProperty(o, 'a', {
    get() { reutrn 1 },
    configurable: false
})

Object.defineProperty(o, 'a', {
    configuration: true
}) // throws a TypeError
Object.defineProperty(o, 'a', {
    enumerable: true
}) // throws a TypeError

delete o.a // Nothing happends
console.log(o.a) // logs 1