proxy,代理器用于修改某些操作的默认行为,包括但不限于拦截默认的get/set等方法。
// target:拦截的目标对象,handler:定制拦截行为
const proxy = new Proxy(target, handler)
Proxy.revocable()方法返回一个可取消的 Proxy 实例
let target = {};
let handler = {};
let {proxy, revoke} = Proxy.revocable(target, handler);
proxy.foo = 123;
proxy.foo // 123
// 取消实例
revoke();
proxy.foo // TypeError: Revoked
拦截方式
- get():拦截对象属性读取
- set():拦截对象属性设置,返回布尔
- has():拦截对象属性检查k in obj,返回布尔
- deleteProperty():拦截对象属性删除delete obj[k],返回布尔
- defineProperty():拦截对象属性定义Object.defineProperty()、Object.- - - - defineProperties(),返回布尔
- ownKeys():拦截对象属性遍历for-in、Object.keys()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols(),返回数组
重点难点
- 要使Proxy起作用,必须针对实例进行操作,而不是针对目标对象进行操作
- 没有设置任何拦截时,等同于直接通向原对象
- 属性被定义为不可读写/扩展/配置/枚举时,使用拦截方法会报错
- 代理下的目标对象,内部this指向Proxy代理
优势:
-
可以直接监听对象而非属性
-
可以直接监听数组的变化
-
有13种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等
-
返回一个新对象,Object.defineProperty只能遍历对象属性修改
-
性能比较好
Reflect:是ES6引入的一个新的对象,他的主要作用有两点,一是将原生的一些零散分布在Object
、Function
或者全局函数里的方法(如apply
、delete
、get
、set
等等),统一整合到Reflect
上,这样可以更加方便更加统一的管理一些原生API
。其次就是因为Proxy
可以改写默认的原生API,如果一旦原生API
别改写可能就找不到了,所以Reflect
也可以起到备份原生API的作用,使得即使原生API
被改写了之后,也可以在被改写之后的API
用上默认的`API