当前位置:优学网  >  在线题库

关于proxy对象的一些疑问

发表时间:2022-06-22 14:02:09 阅读:422

懂了懂了,最开始对proxy的理解有误,感谢各位指点
user === proxyUser -> false
user.wife === proxyUser.wife -> true


看到一些教程,说proxy只拦截一层,就像vue3的shallowReactive,试了下有两个疑问:

  1. 虽然没打印set拦截,但是目标对象user.wife.name的确变了,为什么?
  2. user和proxyUser指向的地址是同一个吗?? ---- 这个我懂了,user === proxyUser是false
let user = {
    name: "foo", 
    age: 25,
    job: ['a', 'b'],
    wife: {
        name: 'bar',
        age: 24
    }
};  
let proxyUser = new Proxy(user, {
     get(target, prop) {
         console.log('劫持get()', prop)
         return Reflect.get(target, prop)
     },
     set(target, prop, val) {
         console.log('劫持set()', prop, val)
         return Reflect.set(target, prop, val);
     },
     deleteProperty (target, prop) {
         console.log('劫持delete属性', prop)
         return Reflect.deleteProperty(target, prop)
     }
 });  

proxyUser.wife.name = 'bb' // 只打印了:劫持get() wife   没有打印:劫持set()
console.log(user.wife.name)    //    打印:bb  ???? why???
🎖️ 优质答案
  • 你是把自己绕晕了吗,只拦截一层,那么wife是第二层所以不打印set不是符合预期吗?直接访问user源对象当然就不走拦截器了这有什么疑问?

  • 你代理的是 user 这个对象,而不是 wife 这个对象

    proxyUser.wife.name = 'bb'

    相当于

    const wife = proxyUser.wife // 先获取 user 的 wife,会被劫持
    wife.name = 'bb' // 然后再设置 wife 的 name,不会被劫持

    想要劫持到 name 的设置,应该代理 wife

    let user = {
        name: "foo", 
        age: 25,
        job: ['a', 'b'],
        wife: {
            name: 'bar',
            age: 24
        }
    };  
    let proxyWife = new Proxy(user.wife, {
         set(target, prop, val) {
             console.log('劫持set()', prop, val)
             return Reflect.set(target, prop, val);
         }
     });  
    
    proxyWife.name = 'bb' // 劫持set() name bb
    console.log(user.wife.name)    //    bb
  • 先把第二个问题说了,肯定不是,如果一样的话,凭什么对proxyUser的访问有拦截,对user的访问没有。代理代理,是目标的代理,总不能我代理我自己吧。

    说回第一个问题:代理归代理,除非你在set里将赋值操作屏蔽掉或者进行修改,否则set操作还是会引用到被代理的对象的,你这里显然没有对赋值操作进行干扰,只是多了一个日志,赋值操作还是会正常的作用于target。

    所谓只拦截一层,因为对target的操作仅限于其自身的属性,user.wife.name实际上是先访问user.wife对应的对象,然后对该对象进行操作,可见目标并不是user。

  • 相关问题