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

参考资料

  • 《es6标准入门》
    最全面,最有良心的Proxy入门