修改Proxy代理的源对象无法触发对应的回调?

128 阅读2分钟

简介

众所周知,Proxy是js内置的标准对象,可以通过new它的构造函数创建一个Proxy的实例对象。创建出的实例对象就称之为源对象的代理对象。

简单的使用proxy

下面我们举个简单的例子:

const obj = {
  name: "proxy",
  age: 18,
  sex: "man",
};
const objByProxy = new Proxy(obj, {
  get(obj, prop) {
    console.log("当前属性值:", obj[prop]);
    return obj[prop];
  },
  set(obj, prop, newVal) {
    console.log("obj", obj, "newVal", newVal);
    return Reflect.set(obj, prop, newVal);
  },
});

此时我们修改、访问objByProxy的属性会调用设置好的callback

objByProxy.name = "hello";
console.log(objByProxy.name);


// 打印结果
obj { name: 'proxy', age: 18, sex: 'man' } newVal hello
当前属性值: hello
hello

此时问题就来了,如果我们修改源对象obj的属性值,objByProxy会改变吗?配置的proxy又会监听到吗?我们在上面的代码基础上运行一下下面两行代码:

obj.name = "hello";
console.log(objByProxy);

// 打印结果:
{ name: 'hello', age: 18, sex: 'man' }

结果是并没有监听到属性值的修改,但是objByProxy确实是改变了。也就是说 objByProxy 和 obj 其实是共用的一块内存。我们可以在控制台打印下 objByProxy:

     Proxy(Object) {name: 'hello', age: 18, sex: 'man'}
      [[Handler]]: Object
      [[Target]]: Object
        1.  age: 18
        1.  name: "hello"
        1.  sex: "man"
        1.  [[Prototype]]: Object
    1.  [[IsRevoked]]: false

我们可以很清楚的看到 objByProxy 实际上是一个Proxy的实例对象。而我们通过 objByProxy.xxx 访问属性的时候其实是访问的是它 Target 属性里的内容,而这个 target 其实就是 obj,并没有生成新的对象,所以修改他俩中的任意一个另一个都会跟随变化。那既然是同一个对象为什么修改源对象的属性我们无法监听到呢?从MDN的描述来看,proxy构造器的第二个入参handler是定义了代理的自定义行为的对象,通过在 handler 对象上定义一组函数,你可以自定义 被代理对象 的一些特定行为,也就是说我们设置的 get、set、delete等仅是 被代理对象 的属性访问器,所以只能监听到 objByProxy 对象上对属性的操作。。。

有什么问题请各位大佬评论区指正。总而言之,言而总之:很烦!!