题意解析

通过 Proxy递归代理 技术,我们能够拦截对象内部嵌套对象的属性访问(get)和属性修改(set)。


代码解析

const obj = {
  nestedObj: { foo: 'bar' }
}

const handler = {
  get(target, prop, receiver) {
    const value = Reflect.get(target, prop, receiver) // 1. 获取属性值
    // 2. 如果属性值是非null对象,则再次用 Proxy 包装 → 递归代理
    if (typeof value === 'object' && value !== null) {
      return new Proxy(value, handler)
    }
    console.log('get', prop, target[prop])
    return value
  },
  set(target, property, value) {
    console.log(`Setting property '${property}' to '${value}'`)
    target[property] = value // 赋值
    return true
  }
}

const proxyObj = new Proxy(obj, handler)

// 访问嵌套对象的属性
console.log(proxyObj.nestedObj.foo)
// 修改嵌套对象的属性
proxyObj.nestedObj.foo = 'baz'

运行结果(概念上)

get foo bar
Setting property 'foo' to 'baz'

说明:

  1. 当我们访问 proxyObj.nestedObj 时,get 拦截触发。
  2. 由于 nestedObj 是对象,get 内部又创建了一个新的 Proxy,实现递归代理。
  3. 访问 nestedObj.foo 时能进入拦截器,修改时也会被 set 捕获。

原理图(Mermaid)

Proxy 层2:代理 nestedObj
Proxy 层1:代理 obj
nestedObj 属性
访问 nestedObj
访问 foo
修改 foo
nestedObj 对象
obj(被代理对象)
foo: 'bar'
触发 set 拦截器

流程说明:

  1. 第一层 Proxy 负责拦截 obj 的直接属性访问。
  2. 如果访问的是对象(nestedObj),就返回一个新的 Proxy 来包裹这个对象。
  3. 于是嵌套对象也有自己的 Proxy 拦截器,从而实现了对内部对象的监听。

刷题笔记

  • 要点1:默认 Proxy 只拦截它直接代理的对象。要监听嵌套对象,必须在 get 中递归创建新的 Proxy。
  • 要点2typeof value === 'object' && value !== null 是判断是否为对象(包括数组)。
  • 要点3:这种方式会在每次访问嵌套对象时创建新 Proxy,要注意性能和内存消耗。
  • 要点4:适合监听较深层次的属性变化(比如做响应式系统)。

更多推荐