Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)。
接收两个参数:被代理者和处理代理的对象
Proxy称为代理,当通过代理来操作被代理者时,会触发代理相关的代码;如果直接操作被代理者,不会触发代理相关代码。
const handler = {get(target, prop, receiver){console.log(target); 被代理者obj对象 {name: "zhu", age: 24}console.log(prop); 被代理者的属性名 nameconsole.log(receiver); Proxy或者继承Proxy的对象 Proxy {name: "zhu", age: 24}return "proxy调用了该方法"}
}
let obj = {name: "zhu",age: 24
}
let proxy = new Proxy(obj, handler);
console.log(obj.name); 打印zhu,无法触发代理代码
console.log(proxy.name); 打印 proxy调用了该方法,触发代理代码中赋值相关的代码
console.log(proxy); Proxy {name: "zhu", age: 24}
(1)handler.get() 方法用于代理处理对象读取属性的操作。
以下是传递给get方法的参数,this上下文绑定在handler对象上.
target目标对象。property被获取的属性名。receiverProxy或者继承Proxy的对象。
返回值:get方法可以返回任何值。
该方法会处理目标对象的以下操作:
- 访问属性:
proxy[foo]和proxy.bar - 访问原型链上的属性:
Object.create(proxy)[foo] Reflect.get()
const handler = {get(target, prop, receiver){console.log(target); 被代理者obj对象 {name: "zhu", age: 24}console.log(prop); 被代理者的属性名 nameconsole.log(receiver); Proxy或者继承Proxy的对象 Proxy {name: "zhu", age: 24}return target[prop];}
}
let obj = {name: "zhu",age: 24
}
let proxy = new Proxy(obj, handler);
console.log(proxy.name); get方法的返回值:zhu
如果违背了以下的约束,proxy会抛出 TypeError:
- 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同。
- 如果要访问的目标属性没有配置访问方法,即get方法是undefined的,则返回值必须为undefined。
关于第一条的异常:只有当configurable和writable同时为false的时候,get方法的返回值不能修改该属性的值,不然会报错。
var obj = {};
Object.defineProperty(obj, "a", { configurable: false, enumerable: false, value: 10, writable: false
});var p = new Proxy(obj, {get: function(target, prop) {return 20;}
});
console.log(p.a); 会抛出TypeError
(2)handler.set() 方法用于代理处理对象设置属性值的操作。
以下是传递给 set() 方法的参数。this 绑定在 handler 对象上。
target 目标对象。
property 将被设置的属性名或 Symbol。
value 新属性值。
receiver 最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。
比如:假设有一段代码执行 obj.name = "jen", obj 不是一个 proxy,且自身不含 name 属性,但是它的原型链上有一个 proxy,那么,那个 proxy 的 set() 处理器会被调用,而此时,obj 会作为 receiver 参数传进来。
const handler = {set(target, prop, value, receiver) {console.log(this); handler对象console.log(target); 目标对象 {name: "zhu", age: 24}console.log(prop); 将被设置的属性名或 Symbol nameconsole.log(value); 设置的属性值 zhuyuzhuconsole.log(receiver); 最初被调用的对象 Proxy {name: "zhu", age: 24}}
}
let obj = {name: "zhu",age: 24
}
let proxy = new Proxy(obj, handler);
proxy.name = "zhuyuzhu";