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

为何Vue3的ref.value无法访问JS私有字段#,却可访问TS的private?

Vue3 ref处理类实例时,JS私有字段与TS private成员的表现差异

我声明了两个类Goods和User:

class Goods {
    #price: number
    #quantity: number

    constructor(price: number, quantity: number) {
       this.#price = price;
       this.#quantity = quantity;
    }

    get totalPrice() {
       return this.#price * this.#quantity;
    }

    totalPriceFunc() {
       return this.#price * this.#quantity;
    }
}

class User {
    private id: number
    private name: string;

    constructor(id: number, name: string) {
       this.id = id;
       this.name = name;
    }

    get info() {
       return `id: ${this.id}, name: ${this.name}`;
    }

    infoFunc() {
       return `id: ${this.id}, name: ${this.name}`;
    }
}

初始化并使用Vue3的ref创建响应式状态后,Goods实例的私有字段无法正常访问,而User实例的TS private成员却能正常使用:

const g = new Goods(10, 100);
console.log('>>>>>>>>g ref before: ', g.totalPrice, g.totalPriceFunc());
// >>>>>>>>g ref before:  1000 1000

const gRef = ref<Goods>(g);
console.log('>>>>>>>>g ref after: ', g.totalPrice, g.totalPriceFunc());
// >>>>>>>>g ref after:  1000 1000

try {
    console.log('gRef totalPrice: ', gRef.value.totalPrice);
    console.log('gRef totalPriceFunc: ', gRef.value.totalPriceFunc());
} catch (e) {
    console.error(e);
    // TypeError: Cannot read private member #price from an object whose class did not declare it
    // ... 错误栈省略
}
-------------------------------------------------------------------

const u = ref<User>(new User(1, 'Daniel'));

console.log('u info: ', u.value.info);
// u info:  id: 1, name: Daniel

console.log('u infoFunc: ', u.value.infoFunc());
// u infoFunc:  id: 1, name: Daniel

核心原因

  • JavaScript私有字段(#price)是语言层面的强限制
    JS的私有字段是ECMAScript标准定义的特性,访问规则极其严格:只有原始类的实例才能访问对应的私有字段。当Vue的ref对Goods实例创建Proxy代理后,gRef.value是代理对象而非原始Goods实例,所以在访问totalPrice getter或调用totalPriceFunc时,JS引擎会直接抛出错误,拒绝代理对象访问私有字段。

  • TypeScript的private仅为编译时检查
    TS里的private关键字只是编译阶段的语法约束,编译成JavaScript后,这些成员会被转换成普通的对象属性(无任何私有标识)。Vue的Proxy代理访问这些属性时,不会受到运行时限制,所以info getter和infoFunc都能正常读取id和name的值。

  • Vue响应式拦截逻辑的影响
    Vue3的ref处理对象时,会通过Proxy拦截所有属性的访问操作。对于JS私有字段,拦截过程中触发的属性访问会直接触发JS引擎的私有字段校验;而TS的private成员因为编译后是普通属性,拦截后可以正常读取原始实例的对应值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 02:33:10