Object.defineProperty()
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法
object.defineProperty(obj, prop, descriptor)
参数
obj
要定义属性的对象
prop
要定义或修改的属性的名称
descriptor
要定义或修改的属性描述符
返回值
被传递给函数的对象
描述
该方法允许精确地添加或者修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到(for...in
或Object.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)。当属性不可配置时,不能在数据和访问器属性类型之间切换。
当试图改变不可配置属性(除了 value
和 writable
属性之外)的值时,会抛出 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
特性表示对象的属性是否可以被删除,以及除value
和writable
特性外的其他特性是否可以被修改
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