有什么用
Proxy类用于创建js对象的代理。proxy实例可以重新定义对象的基本操作,可以用来拦截赋值,防止调用等。
怎么用
Proxy是一个构造器,在js中通过new关键字来创建实例。构造器接受两个参数:
target
用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理,不可以为null,字符串,数字,布尔型,Symbol,undefuned)。
handler
一个定义了被代理对象执行操作时的行为的对象。
一些例子
这里用于展示基本的set和get捕获器的用法。
1 | const obj = { |
可以看到,代理的实例拦截了对原对象的取值和赋值操作。当然proxy还提供了很多其他的捕获器,如 apply
,construct
,defineProperty
,deleteProperty
,has
。。。等等这些,你都可以在这里找到对应的文档:处理器对象 MDN
应用场景
Proxy可以用来实现叫做代理模式的软件开发模式。你可以点击这里了解一下代理模式:代理模式。当然这一篇科普你可能看不懂,看不懂也没关系。建单表述一下,代理就是帮你访问目标实例的中间层。
js的代理和传统的代理模式略有不同,我们可以通过Proxy类方便的创建一个对象的代理,然后对外发布。在这个对象的代理实例中可以简单的控制对象的访问权限,或者帮你访问到你无法/无权访问的实例。下面给出一些我在业务场景中用到Proxy类的例子:
Vue Provide
Vue 在 ^2.2 版本增加了 provide / inject 特性,可以跨多层子孙组件传递祖先组件中的一些状态。本身provide
并不是响应式的。如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。不过有些data属性并不是组件在实例化时就已经存在的,这时候如果你想让子孙组件通过响应式更新这个provide,就必须在外面再套一层,导致用起来结构就比较复杂。这时候可以通过proxy来解决:
父组件:
1 | <template> |
子孙组件:
1 | <template> |
这样,在子孙组件中注入了祖先组件的provideData
后,仍能在asyncData
被赋值后响应式更新自己的内容。
多层代理
在Proxy官方解释中有这么一句话:用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理),当我们代理的targer还是一个代理时,就可以变成一个代理串,每一个代理实例都可以直接使用,也可以拿来生成另一个代理。
我在业务中用来创建了一个axios配置代理,每一层代理实例都可以用来发送xhr请求,当一部分后端接口增加了额外的选项(比如部分接口需要传递额外的header,或者拥有其他的baseURL),就可以用之前的代理实例生成一个新的代理实例,覆盖掉这部分配置。从而减少axios请求部分的代码量。降低code复杂度。
1 | import { extend } from 'lodash' |
拥有了这个功能的axios用起来像是这样:
1 | import axios from 'axios' |
兼容性
写在最后
Proxy类通过简单的方式帮我们创建任意对象的代理,他在没有Proxy时上面的这些操作并不是不能完成,只不过Proxy通过更简单的方法让我们实现这些功能。当然还有很多有趣的逻辑都可以通过Proxy实现。具体怎么做,就需要各位看官自己发掘了。当然你们如果有好的想法,非常欢迎在下面留言教教我~
谢谢观看!