JavaScript类返回Proxy时construct陷阱不触发问题排查
问题根源:
construct陷阱的触发条件误解 你代码里的construct陷阱没触发,核心原因是**construct陷阱只在对Proxy对象本身执行new操作时才会触发**,而你现在的逻辑是在BoundObject的构造函数里返回一个Proxy实例——当你执行new BoundObject(...)时,new操作的目标是BoundObject类,不是这个返回的Proxy,所以construct陷阱根本不会被调用。
正确实现方式:用Proxy包装类本身
要拦截new BoundObject的调用过程,你需要把Proxy直接绑定在BoundObject这个类上,而不是在构造函数内部返回Proxy实例。修改后的代码如下:
class BoundObject { constructor(object, element) { // 把传入对象的属性挂载到实例上 for (const prop in object) { this[prop] = object[prop]; } // 这里不用返回Proxy,Proxy会在外部包装整个类 } } // 用Proxy包装BoundObject类,拦截new操作 const BoundObjectProxy = new Proxy(BoundObject, { construct(target, args) { console.log(`Creating a new ${target.name}`); // 调用原始类的构造函数创建实例 const instance = Reflect.construct(target, args); // 对实例再包装一层Proxy,用来拦截属性设置 return new Proxy(instance, { set: (target, prop, val) => { console.log(`attempting to set ${prop}=${val} type ${typeof val}`); return Reflect.set(target, prop, val); } }); } }); // 现在new的是Proxy包装后的类,会触发construct陷阱 const user = new BoundObjectProxy({name:'fred'}, document.querySelector('#user-form')); user.name = 'mary'; // 依然会触发set陷阱
关键逻辑说明
- 外层Proxy包装
BoundObject类,拦截new操作,这时候construct陷阱会被正常触发,你可以在这里添加实例创建时的逻辑。 - 在
construct陷阱内部,先通过Reflect.construct创建原始类的实例,再给这个实例套一层Proxy来拦截属性的set操作,这样既实现了构造过程的拦截,也保留了属性设置的拦截功能。 - 原来的
set陷阱能正常工作,是因为最终user变量指向的是实例的Proxy,所以设置属性时会触发对应的陷阱。
内容的提问来源于stack exchange,提问作者kiwichris
相关产品推荐
相关产品推荐

