23. Proxy(代理)和Reflect(反射)
1. Proxy:
Proxy
是一个代理器,它可以拦截对目标对象的各种操作,包括读取属性、设置属性、函数调用等等。通过使用 Proxy
,我们可以在这些操作前后注入自定义逻辑,对这些操作进行拦截、修改、记录等等。这使得我们可以更好地控制对象的行为,实现一些高级的功能。
// Proxy get()捕获器和set()捕获器使用
let obj = {
name: "Jack",
age: 20
}
let objProxy = new Proxy(obj, {
get(target, property) {
console.log("获取obj的" + property + "属性");
return target[property]
},
set(target, property, newValue) {
console.log("设置obj的" + property + "属性值为" + newValue);
target[property] = newValue
}
})
console.log(objProxy.name);//获取obj的name属性 Jack
objProxy.age = 30;//设置obj的age属性值为30
console.log(obj.age);//30
2. Reflect:
Reflect
则是一个反射器,它提供了一组可以直接对对象进行操作的方法,这些方法和对象的操作相对应,比如 Reflect.get()
对应对象属性的读取操作,Reflect.set()
对应对象属性的设置操作,Reflect.apply()
对应函数的调用操作等等。通过使用 Reflect
,我们可以更加灵活地控制对象的行为,并且可以在这些操作前后注入自定义逻辑。通常Proxy
与Reflect
一起使用:
// Proxy与Reflect共同使用
let obj = {
name: "Jack",
age: 20
}
let objProxy = new Proxy(obj, {
get(target, property) {
console.log("获取obj的" + property + "属性");
return Reflect.get(target, property)
},
set(target, property, newValue) {
console.log("设置obj的" + property + "属性值为" + newValue);
Reflect.set(target, property, newValue)
}
})
console.log(objProxy.name);//获取obj的name属性 Jack
objProxy.age = 30;//设置obj的age属性值为30
console.log(obj.age);//30
3. 代理捕获器和反射方法
代理可以捕获13种不同的基本操作,这些操作有各自对应的反射API方法和参数。
// 13种代理方法
let obj = {
name: "Jack",
age: 20
}
// obj = function() {} //apply/constructor使用函数
let objProxy = new Proxy(obj, {
// 1. get(目标对象, 属性名, 代理对象)
// get()捕获器会在获取属性值的操作中被调用。对应的反射API是Reflect.get()
get(target, property, receiver) {
console.log("获取属性"+property);
return Reflect.get(...arguments)
},
// 2. set(目标对象, 属性名, 要设置的值, 代理对象)
// set()捕获器会在设置属性值的操作中被调用。对应的反射API是Reflect.set()
set(target, property, newValue, receiver) {
console.log("设置属性值");
return Reflect.set(...arguments)
},
// 3. has(目标对象, 属性名)
// has()捕获器会在in操作符中被调用。对应的反射API是Reflect.has()
has(target, property) {
console.log("in操作符");
return Reflect.has(...arguments)
},
// 4. apply(目标函数, 调用函数时的this, 调用函数时的参数数组)
// apply()捕获器会在调用函数时被调用。对应的反射API是Reflect.apply()
apply(targetFn, thisArg, ...args) {
console.log("函数被调用");
return Reflect.apply(...arguments)
},
// 5. construct(目标构造函数, 构造函数的参数数组, 最初被调用的构造函数)
// construct()捕获器会在new操作符中被调用。对应的反射API是Reflect.construct()
construct(target, args, newTarget) {
console.log("new操作符");
return Reflect.construct(...arguments)
},
// 6. defineProperty(目标对象, 属性名, 属性描述符)
// defineProperty()捕获器会在Object.defineProperty()中被调用。对应的反射API是Reflect.defineProperty()
defineProperty(target, property, discriptor) {
console.log("调用Object.defineProperty() " + property);
return Reflect.defineProperty(...arguments)
},
// 7. getOwnPropertyDescriptor(目标对象, 属性名)
// getOwnPropertyDescriptor()捕获器会在Object.getOwnPropertyDescriptor()中被调用。对应的反射API是Reflect.getOwnPropertyDescriptor()
getOwnPropertyDescriptor(target, property) {
console.log("调用Object.getOwnPropertyDescriptor() " + property);
return Reflect.getOwnPropertyDescriptor(...arguments)
},
// 8. deleteProperty(目标对象, 属性名)
// deleteProperty()捕获器会在delete中被调用。对应的反射API是Reflect.deleteProperty()
deleteProperty(target, property) {
console.log("删除 " + property + " 属性");
return Reflect.deleteProperty(...arguments)
},
// 9. ownKeys(目标对象)
// ownKeys()捕获器会在Object.keys()及类似方法中被调用。对应的反射API是Reflect.ownKeys()
ownKeys(target) {
console.log("拦截获取对象自身属性的操作");
return Reflect.ownKeys(...arguments)
},
// 10. getPrototypeOf(目标对象)
// getPrototypeOf()捕获器会在Object.getPrototypeOf()中被调用。对应的反射API是Reflect.getPrototypeOf()
getPrototypeOf(target) {
console.log("拦截获取对象原型的操作");
return Reflect.getPrototypeOf(...arguments)
},
// 11. setPrototypeOf(目标对象, 新的原型对象)
// setPrototypeOf()捕获器会在Object.setPrototypeOf()中被调用。对应的反射API是Reflect.setPrototypeOf()
setPrototypeOf(target, newProto) {
console.log("拦截设置对象原型的操作");
return Reflect.setPrototypeOf(...arguments)
},
// 12. isExtensible(目标对象)
// isExtensible()捕获器会在Object.isExtensible()中被调用。对应的反射API是Reflect.isExtensible()
isExtensible(target) {
console.log("拦截判断对象是否可扩展的操作");
return Reflect.isExtensible(...arguments)
},
// 13. preventExtensions(目标对象)
// preventExtensions()捕获器会在Object.preventExtensions()中被调用。对应的反射API是Reflect.preventExtensions()
preventExtensions(target) {
console.log("拦截禁止对象扩展的操作");
return Reflect.preventExtensions(...arguments)
},
})
objProxy.name;//1. 获取属性name
objProxy.age = 30;//2. 设置属性值
"name" in objProxy;//3. in操作符
objProxy.apply({
});//4. 函数被调用 注:targetFn应为函数
new objProxy;//5. new操作符
Object.defineProperty(objProxy, 'nickName', {
value: "Jarry" });//6. 调用Object.defineProperty() nickName
console.log(obj);//{name: 'Jack', age: 30, nickName: 'Jarry'}
Object.getOwnPropertyDescriptor(objProxy, "nickName");//7. 调用Object.getOwnPropertyDescriptor() nickName
delete objProxy.nickName;//8. 删除 nickName 属性
Object.keys(objProxy);//9. 拦截获取对象自身属性的操作
objProxy.__proto__;// 10. 拦截获取对象原型的操作
Object.getPrototypeOf(objProxy);//10. 拦截获取对象原型的操作
Object.setPrototypeOf(objProxy, null);//11. 拦截设置对象原型的操作
Object.isExtensible(objProxy);//12. 拦截判断对象是否可扩展的操作
Object.preventExtensions(objProxy);//13. 拦截禁止对象扩展的操作