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 ( eletproxy=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=protoreturntrug 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=protoreturntrue},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()//falsepQ j v * i proxy.m()//true

参考资料

  • 《es6标准入门》
    最全面,最有良心的Proxy入门
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。