为何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实例,所以在访问totalPricegetter或调用totalPriceFunc时,JS引擎会直接抛出错误,拒绝代理对象访问私有字段。TypeScript的
private仅为编译时检查
TS里的private关键字只是编译阶段的语法约束,编译成JavaScript后,这些成员会被转换成普通的对象属性(无任何私有标识)。Vue的Proxy代理访问这些属性时,不会受到运行时限制,所以infogetter和infoFunc都能正常读取id和name的值。Vue响应式拦截逻辑的影响
Vue3的ref处理对象时,会通过Proxy拦截所有属性的访问操作。对于JS私有字段,拦截过程中触发的属性访问会直接触发JS引擎的私有字段校验;而TS的private成员因为编译后是普通属性,拦截后可以正常读取原始实例的对应值。
内容的提问来源于stack exchange,提问作者accbear
相关产品推荐
相关产品推荐

