代理与反射

//创建代理
const target={
    id:'target'
}

const handler = {};

const proxy = new Proxy(target,handler);

//id属性访问同一个值
console.log(target.id);
console.log(proxy.id);

//给代理属性或原始属性赋值,会反映在两个对象上。
// 因为两个对象访问的是同一个值
proxy.id='bar';
console.log(target.id);
console.log(proxy.id)

//Proxy的prototype是undefined因此不能使用instanceof操作符

捕获器参数和反射API

//get()捕获器会接受到目标对象、要查询的属性和代理对象三个参数
const target={
    foo:'bar'
};
const handler={
    get(trapTarget,property,receiver){
        console.log(trapTarget===target);
        console.log(property);
        console.log(receiver===proxy);
    }
}
const proxy = new Proxy(target,handler);
proxy.foo;

代理中的this

在方法中this通常指向调用这个方法的对象。

const target={
    thisValEqualsProxy(){
        return this===proxy
    }
}
const proxy = new Proxy(target,{});
console.log(target.thisValEqualsProxy());//fasle
console.log(proxy.thisValEqualsProxy());//true

如果目标对象依赖于对象标识,可能出现意料之外的问题。

const wm=new WeakMap();
class User{
    constructor(userId) {
        wm.set(this,userId);
    }
    set id(userId){
        wm.set(this,userId);
    }
    get id(){
      console.log(this===proxy);
        return wm.get(this);
    }
}
const user = new User(123);
console.log(user.id);//false 123

const proxy = new Proxy(user,{});
console.log(proxy.id)//true undefined

这是因为User实例一开始使用目标对象作为WeakMap的键,代理对象却尝试从自身取得这个实例。要解决这个问题,就需要重新配置代理,把代理User实例改为代理User类本身。之后再创建代理的实例就会以代理实例作为WeakMap的键了。

const UserClassProxy = new Proxy(User,{});
const proxyUser = new UserClassProxy(456);
console.log(proxyUser.id)//false 456