通常情况下,我们通过 .
或者 []
给对象添加属性:
const o = {}
o.name = 'barwe'
o['age'] = 8
实际上对象的某个属性的操作和特性不仅仅是存值取值这么简答,比如只读属性、存取值时进行一些额外的操作,这些用上面这种定义属性的方式是不能实现的。上面这种简单赋值的方式实际上已经指定了一些默认操作,例如值是可写的,属性可以通过 Object.keys()
访问到等。
Object.defineProperty()
方法提供了一个定制属性特性的方式,基本语法是:
defineProperty<T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>): T;
其中
o
是待添加或者修改属性的对象,它可以是一个原生的 JS 对象或者 DOM 对象p
是属性名称,类型为string | number | symbol
attributes
对属性特性的描述对象
属性描述对象 PropertyDescriptor
的结构如下:
interface PropertyDescriptor {
configurable?: boolean;
enumerable?: boolean;
value?: any;
writable?: boolean;
get?(): any;
set?(v: any): void;
}
configurable
为真表示可以使用Object.defineProperty()
方法再次对属性特性进行配置,或者使用delete
语句移除该属性。默认为false
,即一经配置不能再次配置,而且不能将属性从对象中移除。enumerable
为真时,对对象属性的枚举将包含该元素,典型的就是Object.keys()
方法。默认为false
,即枚举或者迭代对象时该属性是隐藏的。value
指定了属性的初始值,默认为undefined
。writable
为真时表示该属性可以通过赋值操作符修改其值。默认为false
,即不能修改初始值。get
取值器,无参数,返回值作为属性值,默认为undefined
set
存值器,以待存值作为参数,无返回值,默认为undefined
从上面的描述中我们可以知道,默认情况下:
- 普通方法定义的属性可以
delete
掉,defineProperty
方法定义的属性不行 - 普通方法定义的属性可以枚举,
defineProperty
方法定义的属性不行 - 普通方法定义的属性值可以再次修改,
defineProperty
方法定义的属性不行 - 普通方法定义的属性一般没有存取器,
defineProperty
方法定义的属性可以添加,这也是 vue2 响应式原理的基础
参考资料:
评论区