介绍
Proxy
和 Reflect
内置对象从 ECMAScript 2015 开始支持,允许拦截并定义自定义行为。
语法
1 | const p = new Proxy(target, { ...traps }) |
- traps
- 被代理对象上的自定义行为。包含捕获器(操作发生时所对应的处理函数)的方法列表。
- target
- 被代理的目标对象。
1 | const handler = { |
使 Proxy
代理起作用,必须对 proxy 对象 进行操作,而不是原对象。
this 指向
Proxy
代理的原对象内部的this
指向其代理对象。1
2
3
4
5
6
7
8
9const target = {
m () {
return this === proxy;
}
};
const proxy = new Proxy(target, {});
console.log(target.m()); // false
console.log(proxy.m()); // truehandler
拦截函数内部的this
,指向的是handler
对象本身。1
2
3
4
5
6const handler = {
get() {
console.log(this === handler);
}
};
new Proxy({}, handler).foo; // true- 有些原生对象的内部属性,只有通过正确的
this
才能获取。1
2
3
4
5
6
7
8
9
10
11const target = new Date();
new Proxy(target, {}).getDate(); // TypeError: this is not a Date object
const handler = {
get(target, prop) {
const val = target[prop];
return typeof val === 'function' ? val.bind(target) : Reflect.get(...arguments);
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.getDate()); // 可以获取日期
receiver 指向
get
和set
捕获器函数的最后一个参数都是一个receiver
对象,指向当前代理对象。1
2
3
4
5
6const proxy = new Proxy({}, {
get(target, key, receiver) {
return receiver;
}
});
proxy.getReceiver === proxy // true- 但是,代理对象作为其他对象的原型被继承时,
receiver
会指向被继承的对象。1
2
3
4
5
6
7
8
9
10let obj;
const proxy = new Proxy({ foo: 3 }, {
get(target, prop, receiver) {
console.log(receiver === proxy, receiver === obj);
return target[prop];
}
});
console.log(proxy.foo); // true false 3
obj = Object.create(proxy);
console.log(obj.foo); // false true 3 - 在
handler
拦截函数中,如果遇到target
中有定义的getter
,则getter
中的this
指向调用的target
,即不会改变指向,但可以手动将其指向receiver
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const obj = { foo: 1 };
const proxy = new Proxy({
foo: 3,
get info() {
return this.foo;
}
}, {
get(target, prop, receiver) {
console.log(receiver === obj); // true
console.log(target[prop]); // 3
console.log(Reflect.get(target, prop)); // 3
return Reflect.get(...arguments); // Reflect.get(target, prop, receiver)
}
});
Object.setPrototypeOf(obj, proxy);
console.log(obj.info); // 1
参考资料
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 张坤的博客!
评论