ES6:Proxy

概述Proxy 实例的方法Proxy.revocable()this 问题实例:Web 服务的客户端

Proxy 是 ES6 中新增的功能,可以用来自定义对象中的操作,设计思想主要是基于设计模式中的代理模式,其原理图大致如下。

每次获取proxy,这个proxy就会返回对data的深拷贝,而要对data中的属性进行增删查等操作,也是直接对proxy下手就行。通过对整个对象的代理,就避免了访问之前要明确data中有什么属性的这一个过程。这样就实现了一个解耦合的过程,避免了直接操作data对象。基本的使用示例如下。

ES6:Proxy

下面是 Proxy 支持的拦截操作一览,一共 13 种。

1.get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。2.set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。3.has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。4.deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。5.ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。6.getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。7.defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。8.preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。9.getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。10.isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。11.setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。12.apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。13.construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。

二、Proxy 实例的方法

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。

has()方法用来拦截HasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是in运算符。has()方法可以接受两个参数,分别是目标对象、需查询的属性名。

construct()方法用于拦截new命令,下面是拦截对象的写法。construct()方法可以接受三个参数。

target:目标对象。

args:构造函数的参数数组。

newTarget:创造实例对象时,new命令作用的构造函数(下面例子的p)。

deleteProperty方法用于拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。

defineProperty()方法拦截了Object.defineProperty()操作。

三、this 问题

虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。

四、Web 服务的客户端 § ⇧

Proxy 对象可以拦截目标对象的任意属性,这使得它很合适用来写 Web 服务的客户端。

const service = createWebService('http://example.com/data');service.employees().then(json => { const employees = JSON.parse(json); // ···});

上面代码新建了一个 Web 服务的接口,这个接口返回各种数据。Proxy 可以拦截这个对象的任意属性,所以不用为每一种数据写一个适配方法,只要写一个 Proxy 拦截就可以了。

function createWebService(baseUrl) { return new Proxy({}, { get(target, propKey, receiver) { return () => httpGet(baseUrl + '/' + propKey); } });}

同理,Proxy 也可以用来实现数据库的 ORM 层。

参考资料

《js之proxy实现》 

https://blog.csdn.net/qq_38603437/article/details/92855683

《前端进阶之道》 

https://yuchengkai.cn/docs/frontend/

《headfirst设计模式》

ES6:Proxy》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:http://www.hashtobe.com/661.html