9、代理与反射
9.1 代理基础
9.1.1 创建空代理
代理是使用 Proxy 构建函数创建的,需要接收两个参数:目标对象(target)和处理程序对象(handler)。
用比喻的方式的可以:
目标的对象是: 工具人
处理程序对象: 工具人的行为
代理: 对工具人进行控制
// 目标对象
const target = {
id : 'target' // 这里的话,定义一个目标id,不知道能不能用其他的属性,或者多个属性
}
const handler = {}; //先定义一个处理程序对象,到后面可以看到有十三种方法。
// 首先我们定义一个代理
const proxy = new Proxy(target,handler) //放目标对象(target)和处理程序对象(handler)
// 访问目标对象的id
console.log(target.id) // 结果是 target
console.log(proxy.id) // 结果是 target
// 对目标对象的id值进行修改
// 方式一: 直接修改
// 方式二: 代理来进行修改
// 方式一: 直接修改
target.id = '直接修改'
console.log(target.id) // 结果是 直接修改
console.log(proxy.id) // 结果是 直接修改
// 方式二: 代理来进行修改
proxy.id = '代理修改'
console.log(target.id) // 结果是 代理修改
console.log(proxy.id) // 结果是 代理修改
// 使用JavaScript 的hasOwnProperty()来检测一个属性是否是对象的自有属性
// 从下面的结果可以发现,通过代理的方式,也对回到目标对象
console.log(target.hasOwnProperty('id')); //true
console.log(proxy.hasOwnProperty('id')); //true
// instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
// 例子:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car); //输出结果是 true
// 检测Proxy是否在对象的原型链上
console.log(target instanceof Proxy); //Function has non-object prototype 'undefined' in instanceof check
console.log(proxy instanceof Proxy); //Function has non-object prototype 'undefined' in instanceof check
// 也就是说明不在原型链上,换句话说就是 代理是一种特殊的对象
// 代理与目标对象是否一样呢? 答案是不一样!!!
console.log(target === proxy) //false
tips: 这十三种方法有分别是
get( ),
set( ),
has( ),
defineProperty( ),
getOwnPropertyDescriptor( ),
deleteProperty( ),
ownKeys( ),
getPrototypeof( ),
setPrototypeof( ),
isExtensible( ),
preventExtensions( ),
apply( ),
construct( )
9.1.2 定义捕获器(使用代理的主要目的)
从上面的例子中,很难看出代理有什么用, 看上去使用代理好像绕了一个大弯, 不如直接使用目标对象进行操作
这一节的内容就告诉你为什么要使用代理
每次在代理对象调用这些基本操作[就是在处理程序对象中定义的!!!比如上面的十三种 ]时, 代理可以在这些操作传播到目标对象之前先调用捕获器函数, 从而拦截并修改相应的行为。
注意:是有在代理对象上执行这些操作【比如 proxy[property],proxy.property、Object.create(proxy)[property]】才会触发捕获器,在目标对象上执行这些操作不会
//创建一个get()捕获器
// 目标对象
const target = {
foo:'bar'
};
// 处理程序对象
const handle = {
//
get(){
return '捕获,嘻嘻'
}
}
// 创建代理对象
const proxy = new Proxy(target,handle); // 放入两个参数一个是目标对象,一个是处理程序对象(这里面有很多的捕获器)