You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ES6 Proxy捕获ES6 getter的属性访问?

问题原因与修复方案

原因分析

通过Proxy访问ageIn10Years2这个getter属性时,getter函数执行时的this指向原始的Person实例,而非Proxy对象。因此getter内部访问this.ageNow时,是直接读取原始实例的属性,不会经过Proxy的get拦截逻辑,自然不会打印ageNow。

而普通方法ageIn10Years1()的情况不同:调用peter.ageIn10Years1()时,先通过Proxy获取到方法,由于peter是Proxy对象,方法调用时内部的this会指向Proxy,访问this.ageNow会触发Proxy的get陷阱,从而打印ageNow。

修复方案

在Proxy的get陷阱中,判断当前获取的属性是否为访问器属性(getter)。如果是,手动调用getter并将this绑定到Proxy对象,确保getter内部的this指向Proxy,让属性访问经过拦截逻辑。

修改后的代码如下:

class Person {
  public ageNow: number;

  public constructor(ageNow: number) {
    this.ageNow = ageNow;

    const proxy = new Proxy(this, {
      get: (target, property) => {
        console.log(property);
        // 获取属性描述符,判断是否为访问器属性
        const descriptor = Object.getOwnPropertyDescriptor(target, property);
        if (descriptor && typeof descriptor.get === 'function') {
          // 绑定this到proxy后调用getter
          return descriptor.get.call(proxy);
        }
        // 普通属性或方法,直接返回
        const value = target[property as keyof typeof target];
        // 给方法绑定this到proxy,确保任何调用场景下this都指向proxy
        if (typeof value === 'function') {
          return value.bind(proxy);
        }
        return value;
      },
    });
    return proxy;
  }

  public ageIn10Years1() {return this.ageNow + 10;}
  public get ageIn10Years2() {return this.ageNow + 10;}
}

测试验证:

const peter = new Person(18);
console.log(peter.ageIn10Years2);

此时会依次打印ageIn10Years2、ageNow和28,符合预期。

额外给普通方法添加bind(proxy)处理,是为了确保方法无论以何种方式调用(比如被单独提取出来调用),内部的this都指向Proxy,保证拦截逻辑始终生效。


内容的提问来源于stack exchange,提问作者Remirror

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:50:27