懂了懂了,最开始对proxy的理解有误,感谢各位指点
user === proxyUser -> false
user.wife === proxyUser.wife -> true
看到一些教程,说proxy只拦截一层,就像vue3的shallowReactive,试了下有两个疑问:
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???
你代理的是 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。
你是把自己绕晕了吗,只拦截一层,那么wife是第二层所以不打印set不是符合预期吗?直接访问user源对象当然就不走拦截器了这有什么疑问?