🔍 属性描述符
📖 概述
ES5规范引入了属性描述符Property Descriptor
这一概念,它本质上是一个对象,用于描述对象属性的特性,且每个对象属性都关联一个描述符对象。
那对于以传统声明方式定义的属性,其关联的属性描述符对象默认具有哪些特性呢?例如,通过以下方式定义了一个对象,它拥有一个name属性和一个age属性。
const person = {
name : 'FatGod',
age: 18
}
在ES5规范中,怎么获取一个对象属性的描述符对象呢?可以使用规范提供的Object.getOwnPropertyDescriptor
方法来进行获取,该方法的具体用法将在下面讲述。下图为name属性所对应的描述符对象。
==???????????????????????????????????????????????==
属性描述符有两种主要类型,分别为数据描述符和访问器描述符。数据描述符用于表示属性的值以及值是否可写,访问器描述符用于表示属性将如何被读取和写入。描述符只能是这两种类型之一,不能同时为两者。尽管数据描述符和访问器描述符在特性表现上有所差异,它们依然共享一些基本的属性特性。
👥 公共特性
configurable
configurable
为可配置性,当该特性设置为false
时,对应属性将受到如下限制。
- 该属性不可被删除。在JS严格模式下,当试图删除该属性时,将会抛出一个
TypeError
错误。 - 属性描述符不能在数据类型和访问器类型之间切换。
- 属性描述符的特性将不能被更改,当试图更改不可配置属性的描述符特性时,将会抛出一个
TypeError
错误(⭐️⭐️⭐️但是,若它是一个可写的数据描述符,则value
特性依旧可以被更改,writable
特性依旧可以更改为false
)。
enumerable
enumerable
为可枚举性,当该特性设置为false
时,对应属性将受到如下限制。
- 属性不被
Object.assign
或展开运算符...
所考虑。 - 对于非
Symbol
属性,不能够通过for...in
循环、Object.keys
和Object.values
方式进行枚举。
📊 数据描述符特性
value
value
为与属性相关联的值,可以是任何有效的JavaScript值,如数字、字符串、对象、函数等。
writable
writable
为可写性,当该特性设置为false
时,对应属性的值将不可以使用赋值运算符更改。⭐️⭐️⭐️需要注意的是,此时属性是可配置的(configurable
为true
),那么依旧可以通过设置属性描述符的value
特性来更改属性值。
在JS严格模式下,当试图通过赋值运算符来更改不可写属性的值时,将会抛出一个TypeError
错误。
🕵️♂️ 访问器描述符特性
get
get
为getter函数,当访问对应属性时,该getter函数会被无参调用,且函数的返回值会作为属性读取的值。因此,当属性的描述符是访问器类型,且该特性设置为undefined
(未设置)时,对应属性读取的值将永远为undefined
set
set
为setter函数,当对应属性被赋值时,该setter函数会被调用,且携带一个参数,即要赋给属性的值。因此,当属性的描述符是访问器类型,且该特性设置为undefined
(未设置)时,对应属性的赋值将永远被忽略。
🔌 API
用法就是要用TypeScript表示
获取
Object.getOwnPropertyDescriptor
: 返回指定对象属性的描述符对象,若获取不到,则返回undefine
。
tip: 只能获取指定对象自我属性的属性描述符。
Object.getOwnPropertyDescriptors
: 返回一个包含指定对象的所有自我属性描述符的对象,键为属性名,值为对应的属性描述符对象。
定义修改
当通过以上两个获取API得到的属性描述符对象虽然是可变的,但对其进行更改,并不会影响原始属性的配置与特性。ES5中提供了以下两个API来定义或修改对象属性的描述符。
Object.defineProperty
: 向指定对象添加一个属性,或修改现有属性的特性,并返回该对象。Object.defineProperties
: 向指定对象添加一个或多个属性,或修改现有属性的特性,并返回该对象。