一.Proxy
1.概述
(1)概念
Proxy是拦截,代理的意思,即在目标对象前架设一层拦截.
(2)注意
- proxy想要生效,必须在proxy实例上进行相应的操作
- proxy内部的this指向proxy实例而不是目标对象,要注意
2.Proxy实例方法(13种)
(1)get(target,propKey,receiver),拦截对象的读取属性proxy.foo或者proxy[‘foo’]
(2)set(target,propKey,propValue,receiver),拦截目标对象的赋值,如proxy.foo = ‘a’; 或者 proxy[‘foo’] = ‘a’;
(3)has(target,propKey),拦截foo in proxy操作,返回Boolean
(4)deleteProperty(target,propKey),拦截delete proxy[propKey]
(5)ownKeys(target),拦截Object.getPropertyNames(proxy),Object.getPropertySymbols(proxy),Object.keys(proxy)操作,返回数组
(6)getOwnPropertyDescriptor(target,propKey),拦截Object.getOwnPropertyDescriptor(proxy,propKey)返回属性的描述对象.
(7)defineProperty(target,propKey,propDesc),拦截Object.defineProperty(proxy,propKey,propDesc)或者Object.defineProperties(proxy,Descs),返回Boolean
(8)preventExtensions(target),拦截Object.preventExtensions(proxy),返回Boolean值
(9)isExtensible(target),拦截Object.isExtentsible(proxy),返回Boolean值
(10)getPrototypeOf(target),拦截Object.getPrototypeOf(proxy),返回一个对象
(11)setPrototypeOf(target,proto),拦截Object.setPrototypeOf(proxy,proto),返回Boolean,如果目标对象是函数,还有额外2中操作可以拦截
(12)apply(target,object,args),拦截proxy作为函数调用的操作.比如proxy(…args),proxy.call(object,…args),apply(…)
(13)construct(target,args),拦截Proxy实例作为构造函数的操作,例如new proxy(…args);
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
二.Reflect
1.概述
(1)概念
Reflect意为反射,不同于Java的反射机制
(2)设计目的
- 将一些Object上的方法部署到Reflect上
- 修改一些不合理的方法的行为
- 让Object操作变为函数操作,而不是命令操作
- 和Proxy方法上的方法一一对应,可用Reflect完成默认的操作,然后在使用Proxy代理其他的行为
2.静态方法
一一对应于上面proxy的方法,不一一介绍了,参考:
http://es6.ruanyifeng.com/#docs/reflect#%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95
3.使用Reflect实现观察者模式
var person = {
name:'申玉超',
age:123
};
function print() {
console.log(`${person.name},${person.age}`);
}
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});
function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(observer => observer());
return result;
}
observe(print);
var proxyPerson = observable(person);
proxyPerson.name = '李四';
// 李四,123
proxyPerson.age = 456;
// 李四,456