proxy用于修改某些操作的默认行为,等同于在语言层面上修改,所以属于元编程,即对编程语言进行编程。proxy可以理解为在目标对象之前设立一层拦截,外界对该对象的访问都必须通过这层拦截,因此对外界的访问进行过滤或修改,也可以说成是对某些操作进行识别或者修改。
ES6中proxy函数的表现形式:var proxy = new Proxy(target,handler)。new Proxy()表示生成一个proxy实例,target表示拦截的对象,handler表示一个配置对象,包含着为每个需要被拦截的行为提供对应的处理函数,handler如果没有任何设置那么直通原对象。
下面是一些设置的操作:get(target,propKey,reciver)拦截对象属性的获取,但是如果一个属性被配置不可写和不可配置的话那么该属性就不能被代理;set(target,propKey,value,reciver)拦截对象属性的设置;has(target,propKey)拦截propKey in proxy的操作,返回一个布尔值,但是面对不可配置的属性依然会报错,而且has针对for..in无效;deleteProperty(target,propKey)拦截 delete proxy[propKey] 的操作,返回一个布尔值,如果这个方法抛出错误或者返回false当前属性就无法被delete命令删除(属性如果是不可配置的删除会报错);ownkeys(target,propkey)拦截Object.getownPropertyNames(proxy)、Object.getPropertySymbols(proxy)、Object.keys(proxy),返回一个数组,数组成员只能是字符串或者symbol,注意使用object.keys时有三种属性会被ownkeys自动过滤(目标对象上不存在的属性、属性名为symbol的属性、不可遍历的属性),如果目标对象包含不可配置属性那么该属性必须被ownkeys返回,如果目标对象是不可扩展的那么返回的数组中必须包含愿对象中的所有属性且不能包含多余属性。该方法返回目标对象的所有自身属性的属性名,而Object,keys返回的对象仅包括目标对象自身的可遍历属性;getOwnPropertyDescriptor(target,propKey)拦截Object.getOwnPropertyDescriptor(proxy,prpKey),返回属性的描述对象或者undefined;defineProperty(target,propKey,propDesc)拦截Object.defineProperty(target,propKey,propDesc)、Object.defineProperties(proxy,propDesc),返回一个布尔值,如果对象不可扩展则defineProperties不能增加目标对象的属性否则报错,如果目标对象的属性不可配置或不可写那么defineProperty不可更改这个属性;preventExtensions(target)拦截preventExtensions(target),返回一个布尔值,只有目标对象是不可扩展的返回的才是true;getPropertyOf(target)拦截getPropertyOf(target),拦截获取对象原型,返回一个对象或者null否则报错,如果目标对象不可扩展那么返回原型对象;isExtensible(target)拦截Object.isExtensible(proxy),返回一个布尔值,而且该方法返回的值必须和目标对象的isExtensible一致不然报错;setPropertyOf(target,prop)拦截Object.setPropertyOf(proxy,prop), 返回一个布尔值,如果目标对象是不可扩展的那么setPropertyOf方法不得改变目标对象的原型;apply(target,object,args)拦截Proxy作为实例函数调用和call、apply的操作,如proxy(...args),proxy.call(object,...args),proxy.apply(....);construct(target,args)拦截Proxy实例作为构造函数调用的操作,其实就是用于拦截new命令,construct接受两个参数target目标对象,args构造函数的参数对象,construct方法必须返回一个对象,否则报错。
Proxy.revocable返回一个可取消的proxy实例,它返回的是一个对象这个对象的proxy属性是Proxy实例,revoke属性是一个函数可以取消proxy。虽然Proxy可以代理针对目标对象的访问,但是他不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象行为一致,因为在Proxy代理的情况下目标对象内部的this指向proxy代理。