ES6 Proxy 和 Reflect
这两个es6特性 在没用到的时候 真的感觉一无所知,这是啥,能用来干啥?为啥有这些特性?背后有啥目的。说实话如果没有用到过,也没觉得有啥影响,用到了,觉得是真香啊。下面来聊一聊我的一点浅显的看法,欢迎围观。
Proxy
Proxy,翻译过来就是代理,这个也很形象。既然是代理,那它就是负责帮别人做事情,那它能帮哪些人做事呢?在js中,对于基本数据类型,如String、Number、Boolean、Null、Undefined、Symbol这几种是帮不了的,对于复杂数据类型,如Array、Object、Function,它是完全没有问题的,说一声就可以了,肯定帮忙。 既然是代理复杂数据类型,那它能代理哪些功能呢?这里我们要分析一下,找人帮忙,不是所有事情都能帮忙做的,这个要看被代理的人能够做到哪些,人家才会愿意帮你的。下面来看一看哪些能够代理,以下内容摘自阮一峰 ECMAScript 6 入门
- get(target, propKey, receiver) :拦截对象属性的读取,比如
proxy.foo和proxy['foo']。 - set(target, propKey, value, receiver) :拦截对象属性的设置,比如
proxy.foo = v或proxy['foo'] = v,返回一个布尔值。 - has(target, propKey) :拦截
propKey in proxy的操作,返回一个布尔值。 - deleteProperty(target, propKey) :拦截
delete proxy[propKey]的操作,返回一个布尔值。 - ownKeys(target) :拦截
Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。 - getOwnPropertyDescriptor(target, propKey) :拦截
Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。 - defineProperty(target, propKey, propDesc) :拦截
Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。 - preventExtensions(target) :拦截
Object.preventExtensions(proxy),返回一个布尔值。 - getPrototypeOf(target) :拦截
Object.getPrototypeOf(proxy),返回一个对象。 - isExtensible(target) :拦截
Object.isExtensible(proxy),返回一个布尔值。 - setPrototypeOf(target, proto) :拦截
Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 - apply(target, object, args) :拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。 - construct(target, args) :拦截 Proxy 实例作为构造函数调用的操作,比如
new proxy(...args)。
Reflect
Reflect,翻译过来就是映射,反射的意思。那这个对象是什么,能做什么呢? Reflect跟Object对象的功能很类似,可以操作对象的defineProperty、deleteProperty等等,那既然有一个类似的功能,为什么还要有一个Reflect,我们知道设计的基础原则就是要合理,那合理怎么定义呢,这个仁者见仁智者见智,随着es的发展,也慢慢发现之前的设计有些可能不是特别合理,比如defineProperty如果无法定义属性会抛出异常,这个在写程序的时候,看起来很不友好,一堆的try catch,但是基于Reflect定义的属性只会返回false,这样的设计看起来会更合理一些。至于以后,估计随着时代的发展,还会衍生出更合理的方式,但是目前我们静观其变。
Reflect的使用方式
- Reflect.apply(target, thisArg, args)
- Reflect.construct(target, args)
- Reflect.get(target, name, receiver)
- Reflect.set(target, name, value, receiver)
- Reflect.defineProperty(target, name, desc)
- Reflect.deleteProperty(target, name)
- Reflect.has(target, name)
- Reflect.ownKeys(target)
- Reflect.isExtensible(target)
- Reflect.preventExtensions(target)
- Reflect.getOwnPropertyDescriptor(target, name)
- Reflect.getPrototypeOf(target)
- Reflect.setPrototypeOf(target, prototype) 这些跟Object差不多也是一一对应的关系,详细的使用方式可以参考官网。
设计思想
下面聊一聊为啥要有Proxy这个对象,我们知道之前js的数据类型,仅仅是存放数据,获取或者设置一个属性,是不支持函数式的操作,就是说没办法在这一层做拦截,处理一些逻辑操作,比如用户想要赋值之前打印日志,或者不能设置某一个属性的值等等,现在的Proxy更丰富,给用户的操作空间也更多。 Reflect,设计思想也变得更合理,js是单线程的,如果遇到异常,后面的语句就不会执行,就会导致阻塞,而返回false的这个设计使其看起来更加人性化,减少js阻塞的发生。