Proxy
什么Proxy?
proxy是ES6,新增的一个“阻拦器”,也可以理解成是ES6,新增的一种元变编程功用。
作用
proxy用于修正某些操作的默认行为,等同于在语O A D 7 y ? 6 ]言层面* A r V i – . I作出修正。
letproxy=newProxy({},{
get:function(target,property){
return35
}
})
proxy.xxx//35
「Proxy结构函数的解释」
Proxy结构函数承受两个参数,第一个参数是所要署理的方针方针;第二个参数是一个装备方针,关于每一个被署理的操作,需求提供; K # P一个对应的处理函数,该函数将阻拦对应的操作。
Proxy装备方针的一切选项
1.get(target,propKey,receiver)
阻拦方针特点的读取,X ? j [ m ^target是被署理的方针,propK : u w B H { ` sKey是需求阻拦的键,receiver是一个可选的参数。
letobj={
naW z ? u [ i o ;me:"yuefeng"
}
letproxy=newProxy(obj,{
get:function(target,key){
console.log(target,key)
returnt@ 3 D x f r ; ,arget[keyG S h / _ g a]
}
})
console.log6 Y W(proxy- p P z d.name)
2.set(target,propKey,value,rec, { ! 0 Peiver)
阻拦方针特点的设置,target是被署理的方针,propKey是需求阻拦的键,value是要设置的值,receiver是` ` = 7一个可选? s } J . E o G的参数。
letobj={
name:"yueI Y i & 4feng"
}
letpro! U T $ + V F ? 6xy=newProxy? E x(obj,{
set:function(target,key,value){
returntarget[key]=value
}
})
proxy.name='yuej @ - - 0 f l & ifengsu'
conX I t fsole.log(proxy.name)
3.has(target,propKey)
阻拦propKey in targetn Q j的操作,回来一个布d 6 m m尔值。
letobj={
name:"yuefeng"
}
letproxy=nq # q n R ] QewProxy(obj,{
has:function(target,key){
console.log(target,key)
returnkeyintarget
}
})
console.log('namec k R'= 1 X u p 6 *inproxy)
❝
假如原方针不行装备或许制止扩展,那么这是has阻拦会报错;还有has0 6 u e O I k办法阻拦的是Ha5 Z ) ) F PsProperty,而不是HasOwnProperty,所以hasz # * H Z 1 f k办法不判断一个特点是方针本身仍是承继的特点。
❞
4.deleteProperty(tr ; /arget,propKey)
阻拦 delete tar3 = 2 $ 6 ? ]get[propKey]的操作,回来一个布尔值。
letobjl L q . d={
name:"M L N B r - Vyuefeng"
}
letproxy=newProxy(obj,{
deleteProperty:f^ 7 G M - lunctioB ~ Hn(` k R d z | [ target,key){
console.log(target,key)
ifG l )(!(keyintarget))throwTypeError('不存在的key')
returndelete[target,key]
}
})
console.log(deleteproxy['name'])
❝
方针方针本身的~ f o T , F d u !不行装备的特点不能被deleteProperty办法删去,不然会报错。
❞
5j – p ` 4 h 5.ownKeysG 1 y r x M(target)
阻拦Object.getOwnPropertyNames(proxy),Object.getOwnPropertySymbols(proxy),Object.keys(proxy),回来一个数组,该办法回来方针G i Z w +方针所以本身特点的特点名。
letobj={
name:"yuefengz 7 # z A M 7 8 w"
}
letproxK 9 ? I py=newProxy(obj,{
ownKeys:function(targec * q X i E ( st){
console.log(target)
return['name']
}
})
console.log(Object.keys(p- J _ k 1 O { V lroxy))
❝
ownKeys办法回来的数组成员只能是字符串或许Symbol值,假如是其他类型的值,或许回3 k s D D ` v j [来的根本不是数组,就会报错;: H m { Y X n 0 :假如方针方针本身包括不行装备Q $ S的特点,则该特点有必要ownKeys办法回来,不然也会报错;假如方针方针是不行扩展的,这时ownKeys办法回来的数组中有必要包括原方针的所以特点,且不能包括剩余的特点,不@ @ D F ^ J F ( T然也会报错。
❞6 ` ! 7 K ]
6.getOwnPropertyDescriptor(target,propKey)
阻拦Object.getOwnPropertyDescriptor(pron [ U 0 N 9 Q zxy,propKey),回来特点的描绘方针。
letobj={
name:"yuefeng"
}
letproxy=newProxj Q g 3 3 _ = 8y(obj,{
getOwnPropertyDescriptor:func ) D rction(target,key){
console* q B 4 H L m 6.log(target,key)
returnObject.getOwnPropertyDescriptor(target,key)
}
})
console.log(Object.getOwnPropertyDescriptor(obj,+ A @ _ % M z'name'Z t Q u))
7.definePropeA K nrty(target,peopKey,propDesc)
阻拦Object.defineProperty(proxy,propKey,propDesM C b ` H V # /c),Object.defineProperties(pron B [ h M a / sxy,propDesc),回来一个布尔值。
letobj={
name:"yuefeng"
}
letproxy=newProxy(obj,{
defineProperty:function(target,key,desc){
console.log(targ+ n # B N $et,key,desc)
returntrue
}
})
console.log(Object.defineProperty(proxy,'name',{}))
❝
假如方针方针不行扩展,则defineProperty不能添加方针方针中不存在的特点,不然会报错,另外,假如方针方针的某个特点不行写或许不行装备,则defineProperty办法不得改动这两个设置。
❞
8.preventExtensions(target)
阻拦Object.preventExtensions(proxy),回来一个布尔值。
letobj={
n( 6 . . ; s W 7 +ame:"yuefeng"
}
letproxy^ 4 } / N P=newProxy(obj,{
preventExtensions:function(target){
console.log(target)
Object.preventExtev L ^ 1 a G 6nsions(target)
returntrue
}
})
console.log(Object.preventExtensions(proxy)) 7 4 H x F ))
❝
这个办法有一个限制,只有方针方针不行扩展(既o W J Y H MObeject.preventExtensions(proxf S N Z = 3 e #y)为false)proxy.preventExtensions才能回来true,不然会报错。
❞
9.getPrototypeOf(targetx % 3 3 } f , [ Y)
阻拦Object.getPrototypeOf(proxy)Z Z Y = b,回来一个方针。具体阻拦如下
-
Object.prototype.「prot] / U = k do」 -
Object.prototype.isPr$ N B ! O h ) =ototypeOf() -
Object.getPrototypeOf() -
Ref{ } k _lect.getPrototypeOf() -
instanceof
letobj={
naP U O G R a 0 / 7mE ; G ~ ae:"yuefeng"
}j X 8 ( e
letproxy=newProxy(obj,{
getPrototypeOf:function(target){
coT ] Z = }nsoa @ f |le.log(target)
returnobj
}
})
console.loA . A F N 2g(Object.getPrototypeOf(proxy))
❝
getPrototypeOf办法的回来+ % : n V & 值有必要是方针或许+ x e Y )是null,不然会报错。另外,假如方针方针不行扩展,getPrototypeOf办法有必要回来方针方针的原型方针。
❞
10.isExtensible(target)
阻拦Object.isExtensible(proxy),回来一个布w . : 0尔值。
letI 6 I 0 . 4 U s 6obj={
name:/ ^ #"yuefeng"
}
letproxy=newProxy(obj,{
isExtensible:function(target){
console.log(tI j ; ; N AargetA v L)
returntrue
}
})
cu j (onsole.log(Object.isExtensible(proxy))
❝
该办法只能回来布尔值,: Y G c r不然回来的值会被主动转为布尔值。
❞
11.setPrototypeOf(target,proto)
阻拦Object.setPrototypeOf(proxy,proto),X L / t c X回来一个布尔值。
letobj={
name:"yuefeng"
}
letproxy=newProxy(obj,{
sd v 8 N y qetProt: V S 0otypeOf:function(target,proto){
console.log(target,proto)
target.prototype=proto
returntrug 1 V [ l F je
}
})
console.log(Object.setPrototypeOf(proxy,obj))
❝
该办法只能回来布尔值,不然会被主动转为布尔值。另外,假如方针方针不行扩展,setPrototypeOf办法不得改动方针方针的原型。
❞
12.apply(target,object,args)
阻拦Proxy实例,并将其作为函数调用的操作,比方proxy(…args)、pro6 8 F : Y C C @xy.call(object,…args)、proxy.apply(object,…args)。
letproxy=newProxy(Person,{
apply:function(targetC ` n T y * t,ctx,args){
console.log(target,ctx,args)
return'iamaboy'
}
})
functionPerson(){
red 1 v 6 Pturn'iamagril'
}
console.log(proxy())
13.construcS o e 0t(target,args)
阻拦Proxy实2 [ a d e C 2 A例作为结构函数调用的操作,比方new proxy(…args)。
letproxy=newProxy(Person,{
construct:funci F H V _ # G 0tion(target,args){
console.log(target,args)
return{value:'18'}X s T Q - d
}
})
functionPerson(){
return'iamagril'
}
console7 : h D f A.log(newproxy().value)
❝
construct办法有必要回来一个方针,不然会报错。
❞
完整代码
letprox? v } X @ ey=newProxy({},{
get:function(target,key){
console.log(target,key)
returntarget[key) 5 / U a t]
},
set:function(target,key,value){
returntarget[key]=value
},
has:function(target,key){
console.log(target,key)
returnkeyintarT W D b 3 Y = m $get
},
de[ O (leteProperty:functiM X ` * R won(target,key){
console.logm l / + ? 7 [ , f(target,key)
if(!(keyintarget))throwTypeError('不存在的key')
returndelete[target,key]
},
ownKeys:function(target){
console.log(target)
return['name']
},
getOwnPropertyDescriptor:function(taQ o m ) f 3rget,key){
console.log(target,key)
returnObject.getOwnPropertyDescriptor(target,key)
},
def+ O 1 B ; w TineProperty:funct* ; a } Qionl q c d(targete I _ u _ N R,key,desc){
console.log(target,kC i Gey,desc)
returr h s = S O N ntrue
},
preventExtensions:function(target){
console.log(target)
Object.preventExtensions(target)
returntrue
},
getPrototypeOf:function(target){
consolB u R G s Ee.logg a Z h - W % k ~(target)
returnobj
},
isExtensible:function(target){
console.log(tK ` H ~ @ d m Farget)
returntrue
},
setPrototypeOf:function(target,pro[ : w % 8to){
conso{ L 5 T ? z dle.loF } j D 4 6 f Gg(ta* { g k F 8 H x Prget,proe l B G M u j ` zto)
t: n 9 7 w d . karget.prototype=proto
returntrue
},
apply:fF 7 u W u @ )unction(target,ctx,args){
consS 9 } & J 7ole% = P =.log(target,ctx,args)
return'iamaboy'
},
construct:function(target,args){
console.log(target,$ H k [args)
return{value:8 ? 3 U'18'}
}
})
注意⚠️问题
this问题
「Proxy可以署理针对方针方针的拜访,但它不是方针方针的透明署理,既不做任何阻拦的情况g m ~ k下也无法保证于方针s X M & i方针的行为一致。主要原因就是Proxy署E T 1 Z理的情况下,方针方针内部的this关键^ o m : c e字会指向Proxy署理」
consttX # K 1arget={
m:function(){
console.log(this % m t===proxy)
}
}
constproxy=newProxy({},{})
target.m()//false
pQ j v * i proxy.m()//true
参考资料