本篇文章总结控制对象访问的相关 API。
Object.defineProperty
Object.defineProperty
可以对对象的属性进行配置,它接收如下参数:
obj
:对象prop
:属性descriptor
:属性描述符
其中 descriptor
包括如下配置选项
value
:属性的值writable
:属性是否可写,默认为false
set
:为属性设置值时会触发此方法,设置的新值会作为参数传入get
:访问此属性是会触发此方法configurable
:该属性是否可再次进行配置,默认为false
enumerable
:是否可遍历,默认为false
其中 value
与 writable
是一组,set
和 get
是一组,二者不可同时使用。
例子1
const obj = {} |
在上面我们为 obj
的 name
属性配置了 value
属性为 Alice
作为 obj.name
的初始值,又配置了 writable
为 false
,表明该属性是不可写的,对该属性进行赋值时无效的。
例子2
const obj = {} |
上面我们为 obj
的 name
属性配置了 set
和 get
方法,没当我们为 obj.name
赋予新值时都会调用 set
方法,并将新值传入,在 set
方法中,我们对新值进行了判断,如果新值为 Alice
则我们赋值给 username
;每次当我们访问 obj.name
时,则会触发 get
方法,在 get
方法中我们直接返回了 username
这个变量的值,通过这种方式可以控制对象属性的访问操作。
例子3
const obj = { |
在上面我们定义了一个 obj
对象,其中有 a, b
两个属性,默认都是可枚举的。通过 Object.keys
方法可以取得对象中所以可枚举的属性,这时它们都在返回的数组中;接着我们配置 a
为不可枚举,此时再次调用 Object.keys
,此时 a
就不在返回的数组中了。
例子4
const obj = { |
上面我们配置了 a
为不可枚举,并且配置 configurable
为 false
,然后接着我们又想配置属性 a
为可枚举的,但是会报错 TypeError: Cannot redefine property: a
,这是因为我们配置 configurable
为 false
,表示不可再次配置,当我们再次对属性 a
进行配置便会报错。
const obj = { |
Object.defineProperties
Object.defineProperties
每次只能配置对象的一个属性,而 Object.defineProperties
可以一次性配置对象的多个属性,它的语法如下:
Object.defineProperties(obj, { |
见下例:
const obj = { |
Object.preventExtensions
Object.preventExtions(obj)
可以使得对象 obj
不可扩展,即不能为对象添加新的属性
const obj = { |
上面我们将 obj
设置为不可扩展后试图添加新的属性,但是并没有成功。设置为不可扩展后,我们可以正常访问现有对象上的属性,以及更改和删除
const obj = { |
对象一旦变为不可扩展后,就一直是不可扩展的。通过 Object.isExtensible
方法可以判断一个对象是否是可扩展的
const obj = { |
Object.seal
seal
的意思是封印,Object.seal
比 Object.preventExtensiable
更近一步,被 seal
了的对象,除了变为不可扩展,还不可配置 configurable: false
,属性不能被删除了以及属性不能被 Object,defineProperty
进行配置了
const obj = { |
但是我们还可以对象现有的属性进行更改的
const obj = { |
通过 Object.isSealed
可以判断对象是否被 seal
了
const obj = {} |
Object.freeze
freeze
是冻结的意思,它相对于 Object.seal
更进一步,不仅不可扩展,不可配置,对象的数据熟悉 writable
会被设置为 false
const obj = { |
但是如果有定义 set
方法的话,对象属性还是可以被修改的
const obj = { |
通过 Object.isFrozen
方法可以判断一个对象是否被 freeze
了
const obj = {} |
Proxy
Proxy
是 ES6
中的新特性,它可以为对象做一层代理,当用户通过代理访问对象时,代理可以拦截一些操作,例如为属性赋值,访问属性的值,从而控制对象的访问。Proxy
可以拦截 13 种操作,这里不会详细介绍,只会介绍 set
和 get
拦截。
Proxy
的语法如下
const proxy = new Proxy(target, { |
例子1
const target = { |
上面我们为 target
对象做了层代理,当我们通过代理赋值时,会被 set
方法拦截,set
方法接收四个参数:
trapTarget
:被代理的对象key
:被赋值的属性value
:被赋的值receiver
:操作发生的对象,即代理对象
上面我们只允许对 age
属性赋值,并且赋的值不能大于 18
。
例子2
const target = { |
我们对 target
的 get
方法进行了代理,当我们通过代理对象访问属性值时,如果访问的是 age
属性,则返回 18
,其他属性不做处理直接返回原值。
如果直接通过
target
访问属性的话,操作是不会被拦截的,代理没有作用。
参考文献
- Object.defineProperty
- Proxy和Relect
- 《JavaSCript高级程序设计》,第三版