构造函数可通过显式返回 proxy 实例间接实现属性操作拦截;需用 object.create 指定原型并手动处理 constructor 等特殊属性,以保留 instanceof 和继承关系。

构造函数本身不能直接返回代理对象来拦截实例属性操作,但可以通过在构造函数中返回一个 Proxy 实例,间接实现对新创建对象的属性访问、赋值等行为的拦截。关键在于:**构造函数若显式返回一个对象(非 null 的对象),则 new 表达式的结果就是该对象,而非默认的 this**。
构造函数返回 Proxy 的基本写法
在构造函数内部创建目标对象(如普通对象或 class 实例),再用 new Proxy(target, handler) 包裹它,并返回该 Proxy。这样 new 出来的“实例”实际是代理,所有属性操作都会经过 handler 拦截。
- 目标对象可以是空对象
{},也可以是已有类的实例(需注意原型链) - 必须显式 return Proxy,否则 new 仍返回默认 this
- Proxy 的
handler.get/set等方法可自定义逻辑,比如日志、校验、响应式触发
正确保留原型链(避免 instanceof 失效)
直接返回 Proxy 会导致原型丢失,instanceof 和方法继承可能异常。解决方案是在 handler 中手动代理 constructor 和 prototype 相关行为,或更稳妥地:把 Proxy 套在真正的实例上,并确保其 [[Prototype]] 指向原构造函数的 prototype。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 推荐做法:先用
Object.create(YourClass.prototype)创建目标对象,再 Proxy 它 - 在 handler.get 中,对
constructor、__proto__、toString等特殊属性做透传或适配 - 例如:
if (key === 'constructor') return target.constructor;
实际示例:带属性访问日志的构造函数
下面是一个记录所有 get/set 操作的构造函数:
function LoggedObj(name) {
const target = Object.create(LoggedObj.prototype);
target.name = name;
<p>return new Proxy(target, {
get(obj, key) {
console.log(<code>[GET] ${key}</code>);
return Reflect.get(obj, key);
},
set(obj, key, val) {
console.log(<code>[SET] ${key} = ${val}</code>);
return Reflect.set(obj, key, val);
}
});
}
LoggedObj.prototype.sayHi = function() {
return <code>Hi, ${this.name}</code>;
};</p><p>const a = new LoggedObj('Alice');
console.log(a.name); // [GET] name → "Alice"
a.age = 30; // [SET] age = 30
console.log(a.sayHi()); // [GET] sayHi → "Hi, Alice"
</p>
注意事项与限制
这种模式虽灵活,但有几点必须留意:
- 无法拦截私有字段(#field),Proxy 对 # 语法无效
- 不能拦截 for...in、Object.keys() 等枚举操作,需配合
ownKeys和getOwnPropertyDescriptor - 严格模式下,
sethandler 必须返回布尔值表示是否成功 - 箭头函数无
this,不适用于需要动态绑定的场景;建议用普通函数声明构造函数










