JavaScript中的Proxy
前言
这个和之前的Reflect有一定的关系,也是Vue3实现的一个很重要的API,学学学。
Proxy
顾名思义,就是一个代理对象,通过一组配置函数来拦截操作从而使得以源对象得以被扩展。
Proxy
是一个构造函数
由两个参数
obj
需要代理的对象handler
一组由特定的处理函数组成的对象,如果没有指定,则会使用源对象的默认行为。
1 | var o = {}; |
在Reflect上的方法,Proxy都可以拦截,具体包括
getPrototypeOf
setPrototypeOf
isExtensible
preventExtensible
getOwnPropertyDescriptor
defineProperty
has
get
set
deleteProperty
ownKeys
apply
construct
getPrototypeOf()
读取代理对象的原型时,这个方法就会调用
有一个参数
obj
源对象
该函数必须返回一个对象或者null
1 | var o = {}; |
可以触发该函数的操作包括
Object.getPrototypeOf
Reflect.getPrototypeOf
__proto__
Object.prototype.isPrototypeOf
instanceof
1 | var proxy = new Proxy({},{ |
setPrototypeOf()
设置代理对象的原型时,这个方法就会调用。
有两个参数
obj
源对象prototype
将设置的原型对象
该函数在设置prototype成功返回true,失败返回false
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
Reflect.setProtytpeOf
Object.setPrototypeOf
isExtensible()
查询代理对象是否可以扩展时,这个方法就会调用。
有一个参数
obj
源对象
返回值必须为一个boolean值或者可以转为Boolean的值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
Reflect.isExtensible
Object.isExtensible
preventExtensions()
禁止代理对象扩展时,这个方法就会调用。
有一个参数
obj
源对象
返回值必须为一个boolean值或者可以转为boolean的值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
Reflect.preventExtensions
Object.preventExtensions
getOwnPropertyDescriptor()
获取对象属性的属性描述符时,这个方法会调用。
有两个参数
obj
源对象propertyKey
需要获取属性描述符的属性名
返回值必须为一个对象或者undefined
1 | var proxy = new Proxy({ |
可以触发该函数的操作包括
Reflect.getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor
defineProperty()
在定义代理对象的属性时,这个方法会调用。
有三个参数
obj
源对象propertyKey
将设置的属性名descriptor
将设置属性的属性描述符
返回值必须为一个boolean值或者可以转为boolean的值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
Reflect.defineProperty
Object.defineProperty
proxyObj.propertyKey = value
has()
在检查属性是否存在对象中时,这个方法会调用。
有两个参数
obj
源对象propertyKey
需要检查的属性名
返回值必须为一个boolean值或者可以转为boolean的值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
propertyKey in proxy
propertyKey in Object.create(proxy)
Reflect.has
with
操作
get()
在读取代理对象属性时,这个方法会调用。
有三个参数
obj
源对象propertyKey
要获取的属性名context
要绑定到getter的上下文,默认为调用对象本身。
返回值可以为任何值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
proxy[propertyKey]
或者proxy.propertyKey
Object.create(proxy)[propertyKey]
或者Object.create(proxy).propertyKey
Reflect.get
set()
在设置代理对象属性值时,这个方法会调用。
有四个参数
obj
源对象propertyKey
设置的属性名value
设置的属性值context
要绑定到setter的上下文,默认为调用对象本身。
TIPS:
对于get
和set
,其中context
参数的传入通常是proxy
对象本身,但是对于处于原型链上的proxy
,传入的就不是proxy
对象了,而是触发操作的那个对象,比如,obj.propertykey = value
,obj
不是代理对象,但是obj
的原型链上存在代理对象proxy
,那传入context
参数的就是obj
而不是proxy
了。而对于通过Reflect.set
操作触发,context
参数就跟set
函数指定的一样了。
返回值必须为一个boolean值或者可以转为boolean的值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
proxy[propertyKey] = value
或者proxy.propertyKey = value
Object.create(proxy)[propertyKey] = value
或者Object.create(proxy).propertyKey = value
Reflect.set
deteleProperty()
在删除对象的属性时,这个方法会调用
有两个参数
obj
源对象propertyKey
将删除的属性名
返回值必须为一个boolean值或者可以转为boolean的值。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
delete proxy[propertyKey]
或者delete proxy.propertyKey
Reflect.deleteProperty
ownKeys()
获取代理对象属性名组成的数组时,这个方法会调用
有一个参数
obj
源对象
返回值必须为一个可枚举的对象。
1 | var proxy = new Proxy({},{ |
可以触发该函数的操作包括
Object.getOwnPropertyNames
Object.getOwnPropertySymbols
Reflect.ownKeys
Object.keys
apply()
在对代理对象进行函数调用时,这个方法会调用
有一个参数
fn
源函数context
执行函数的上下文args
参数的数组
返回值可以为任意值。
1 | function fn(msg){ |
可以触发该函数的操作包括
proxy(arg1,arg2,...,argN)
Function.prototype.apply
或者Function.prototype.call
Reflect.apply
construct()
以代理对象为构造器或者原型上存在代理对象的构造器生成对象时,这个方法会调用
有三个参数
obj
源对象(可以被new
)args
参数数组newTarget
被调用的构造函数
返回值必须为一个对象
1 | function fn(name){ |
可以触发该函数的操作包括
new proxy(arg1,arg2,...,argN)
Reflect.construct
后记
学完感觉我能看懂vue3源码了。