Proxy
一个 Proxy 对象包装另一个对象并拦截诸如读取/写入属性和其他操作,可以选择自行处理它们,或者透明地允许该对象处理它们。
参数详解
target
目标对象。
property
被获取的属性名。
receiver
Proxy 或者继承 Proxy 的对象
TIP
继承 Proxy 对象举例:
jslet foo = { name: "foo" }; let proxyFoo = new Proxy(foo, {}); let bar = Object.create(proxyFoo);
代理过程
- eg1
js
let bar = "bar";
let foo = {
get name() {
console.log("call obj name.");
return bar;
},
set name(val) {
bar = val;
},
};
let proxyFoo = new Proxy(foo, {
get: function(target, property, receiver) {
console.log("call proxy1 name.");
return Reflect.get(target, property, receiver);
},
});
let voo = new Proxy(proxyFoo, {
get: function(target, property, receiver) {
console.log("call proxy2 name.");
return Reflect.get(target, property, receiver);
},
});
console.log(voo.name);
// call proxy2 name.
// call proxy1 name.
// call obj name.
// bar
- eg2
js
let foo = {
bar: "bar",
get name() {
console.log("call obj name.");
return this.bar;
},
set name(val) {
this.bar = val;
},
};
let proxyFoo = new Proxy(foo, {
get: function(target, property, receiver) {
console.log("call proxy1 name.");
return Reflect.get(target, property, receiver);
},
});
let voo = new Proxy(proxyFoo, {
get: function(target, property, receiver) {
console.log("call proxy2 name.");
return Reflect.get(target, property, receiver); // receiver 换为proxyFoo 或者 foo
},
});
console.log(voo.name);
改变 20 行参数后结果
receiver
call proxy2 name.
call proxy1 name.
call obj name.
call proxy2 name.
call proxy1 name.
bar
proxyFoo
call proxy2 name.
call proxy1 name.
call obj name.
call proxy1 name.
bar
foo
call proxy2 name.
call proxy1 name.
call obj name.
bar
Reflect
Reflect.get()
方法与从 对象 (target[propertyKey]
) 中读取属性类似,但它是通过一个函数执行来操作的。
- 语法:
Reflect.get(target, propertyKey[, receiver])
- 参数:
param | meaning |
---|---|
target | 需要取值的目标对象 |
propertyKey | 需要获取的值的键值 |
receiver | 如果target 对象中指定了getter ,receiver 则为getter 调用时的this 值。会改变this 指向 |
Map、Set、WeakSet、WeakMap 的监听
js
let map = new Map([["name", "zhengcaiyun"]]);
let mapProxy = new Proxy(map, {
get(target, key, receiver) {
console.log("取值:", key);
return Reflect.get(target, key, receiver);
},
});
mapProxy.get("name");
Uncaught TypeError: Method Map.prototype.get called on incompatible receiver [object Object]
Map、Set 对象赋值、取值和他们内部的 this 指向有关系,但这里的 this 指向的是其实是 Proxy 对象,所以得这样干
js
let map = new Map([["name", "wangyangyang"]]);
let mapProxy = new Proxy(map, {
get(target, key, receiver) {
var value = Reflect.get(...arguments);
console.log("取值:", ...arguments);
return typeof value == "function" ? value.bind(target) : value;
},
});
mapProxy.get("name");
js
let foo = new Map();
foo.set(1, 2);
let bar = new Proxy(foo, {
get() {
return Reflect.get(...arguments);
},
});
bar.get; // foo实例的get方法
bar.get(1); // foo实例的get方法在bar对象上调用,相当于get方法里的this指向了bar
console.log(bar.get.call(foo, 1)); //重新给指向this