interface User {
name: string,
age: number
}
const person: User = {name: 'menffyzheng', age: 18}
// Proxy第一个参数,代理的目标只能是对象、数组、函数、set、map,其他类型会报错
const personProxy = new Proxy(person, {
// 取值
get(target: User, p: string | symbol, receiver: any): any {
if (target.age <= 18) {
return Reflect.get(target, p, receiver);
} else {
return 'menffyzheng成年了';
}
},
// 赋值
// set(target: User, p: string | symbol, value: any, receiver: any): boolean {
// return true;
// },
// // 拦截函数调用
// apply(target: User, thisArg: any, argArray: any[]): any {
// },
// // 拦截in操作符
// has(target: User, p: string | symbol): boolean {
// return true;
// },
// // 拦截 for in 方法
// ownKeys(target: User): ArrayLike {
// },
// // 拦截new操作符
// construct(target: User, argArray: any[], newTarget: Function): object {
// return {};
// },
// // 拦截删除操作
// deleteProperty(target: User, p: string | symbol): boolean {
// return true;
// }
})
console.log(personProxy.age)
对象取值方法除了可以
person.age
也可以Reflect.get(person, 'age', person)
Reflect里的receiver参数位置,也就是Reflect.get方法里的第三个参数,是为了保证上下文的正确而使用的,它其实就等于第一个参数。
// 观察者模式,类似vuex的状态变化监控,我觉得跟watch方法也很类似
const list: Set = new Set();
const autoRun = (cb: Function) => {
if (!list.has(cb)) {
list.add(cb);
}
}
const observable = (params: T) => {
return new Proxy(params, {
set(target: T, p: string | symbol, value: any, receiver: any): boolean {
const result = Reflect.set(target, p, value, receiver);
list.forEach(fn => fn());
return result;
}
})
}
const paramsProxy = observable({name: 'menffyzheng', attr: 'test'})
autoRun(() => {
console.log('执行通知函数,有变化了!!')
})
console.log(paramsProxy.name);
paramsProxy.attr = 'test2'
paramsProxy.attr = 'test3'