如何为枚举创建Proxy?为何枚举的Proxy未生效?
为什么Proxy在枚举上没生效?
看起来你搞混了修改Proxy对象的属性和覆盖包含Proxy的类属性这两种操作的区别,我来拆解一下问题:
核心问题:你可能是在覆盖this.status属性,而不是修改Proxy内部的枚举对象
你的代码里是把Status枚举用Proxy包装后,赋值给了MyClass的status属性。但如果你执行的是类似this.status = Status.Middle这样的代码,你并不是在修改Proxy包装的枚举对象的属性——而是直接把MyClass实例上的status属性整个替换成了Status.Middle这个枚举值,原来的Proxy实例直接被丢弃了,自然不会触发它的set陷阱。
两种场景的解决方案
场景1:你想监听MyClass实例的status属性赋值操作
如果你的需求是监听类实例的status属性被修改,那Proxy不该套在枚举上,而是应该用类的setter/getter(更直观),或者把Proxy套在类实例上:
方案A:使用类的setter(推荐)
export enum Status { Beginning, Middle, Ending } export class MyClass { private _status: Status = Status.Beginning; get status() { return this._status; } set status(value: Status) { console.log('I have been set'); this._status = value; } } // 使用示例 const obj = new MyClass(); obj.status = Status.Middle; // 会输出"I have been set"
方案B:用Proxy包装类实例
export enum Status { Beginning, Middle, Ending } export class MyClass { public status: Status = Status.Beginning; } // 创建实例时用Proxy包装 const obj = new Proxy(new MyClass(), { set(target, prop, value) { if (prop === 'status') { console.log('I have been set'); } return Reflect.set(target, prop, value); } }); obj.status = Status.Ending; // 会输出"I have been set"
场景2:你确实想修改枚举对象的属性(不推荐)
如果你的需求是监听枚举对象自身的属性修改(比如this.status.Beginning = 10),那Proxy其实是可以生效的,但要注意:枚举的设计初衷是固定常量集合,修改枚举属性会破坏它的语义,而且TypeScript编译后的数字枚举是双向映射的,修改会影响反向映射(比如Status[0]原本指向"Beginning",修改后会混乱)。
不过如果一定要这么做,你的Proxy代码本身是没问题的,比如:
export enum Status { Beginning, Middle, Ending } export class MyClass { public status = new Proxy(Status, { set: (target, propertyKey, value) => { console.log('I have been set'); return Reflect.set(target, propertyKey, value); } }) } const obj = new MyClass(); obj.status.Beginning = 10; // 会输出"I have been set"
总结
大多数情况下,你应该是想监听类实例的status属性赋值,这时候用类的setter是最清晰的方案;如果一定要用Proxy,记得把它套在类实例上,而不是枚举对象上。
内容的提问来源于stack exchange,提问作者Get Off My Lawn
相关产品推荐
相关产品推荐

