前言
ES6新增的代理
和反射
为开发者提供了拦截并向基本操作嵌入额外行为的能力
。具体地说,可以给目标对象定义一个关联的代理对象,而这个代理对象可以作为抽象的目标对象来使用。在对目标对象的各种操作影响目标对象之前,可以在代理对象中对这些操作加以控制。
Proxy (代理)
代理是使用 Proxy
构造函数创建的。这个构造函数接收两个参数:目标对象和处理程序对象。缺少其中任何一个参数都会抛出 TypeError。
创建空代理
如下面的代码所示,在代理对象上执行的任何操作实际上都会应用到目标对象。唯一可感知的不同
就是代码中操作的是代理对象。
const target = {
id: 'target'
};
const handler = {};
const proxy = new Proxy(target, handler);
// id 属性会访问同一个值
console.log(target.id); // target
console.log(proxy.id); // target
// 给目标属性赋值会反映在两个对象上
// 因为两个对象访问的是同一个值
target.id = 'foo';
console.log(target.id); // foo
console.log(proxy.id); // foo
// 给代理属性赋值会反映在两个对象上
// 因为这个赋值会转移到目标对象
proxy.id = 'bar';
console.log(target.id); // bar
console.log(proxy.id); // bar
定义捕获器
捕获器可以理解为处理程序对象中定义的用来直接或间接在代理对象上使用的一种“拦截器”,每次在代理对象上调用这些基本操作时,代理可以在这些操作传播到目标对象之前先调用捕获器函数,从而拦截并修改相应的行为。
const target = {
foo: 'bar'
};
const handler = {
// 捕获器在处理程序对象中以方法名为键
get() {
return 'handler override';
}
};
const proxy = new Proxy(target, handler);
console.log(target.foo); // bar
console.log(proxy.foo); // handler override
get()
捕获器会接收到目标对象,要查询的属性和代理对象三个参数。我们可以对上述代码进行如下改造
const target = {
foo: 'bar'
};
const handler = {
// 捕获器在处理程序对象中以方法名为键
get(trapTarget, property, receiver) {
console.log(trapTarget === target);
console.log(property);
console.log(receiver === proxy);
return trapTarget[property]
}
};
const proxy = new Proxy(target, handler);
proxy.foo;
// true
// foo
// true
console.log(proxy.foo); // bar
console.log(target.foo); // bar
处理程序对象中所有可以捕获的方法都有对应的反射(Reflect)API 方法。这些方法与捕获器拦截的方法具有相同的名称和函数签名,而且也具有与被拦截方法相同的行为。因此,使用反射 API 也可以像下面这样定义出空代理对象:
const target = {
foo: 'bar'
};
const handler = {
get() {
// 第一种写法
return Reflect.get(...arguments);
// 第二种写法
return Reflect.get
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.foo); // bar
console.log(target.foo); // bar
我们也可以以此,来对将要访问的属性的返回值
进行修饰。
const target = {
foo: 'bar',
baz: 'qux'
};
const handler = {
get(trapTarget, property, receiver) {
let decoration = '';
if (property === 'foo') {
decoration = ' I love you';
}
return Reflect.get(...arguments) + decoration;
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.foo); // bar I love you
console.log(target.foo); // bar
console.log(proxy.baz); // qux
console.log(target.baz); // qux