proxy 无法拦截对普通对象的 new 调用,因为普通对象无[[construct]]内部方法,new {} 语法非法;只能代理函数或类,并通过 construct 拦截器捕获 new proxy(...)。

Proxy 无法拦截对象的构造函数调用。这是 JavaScript 的语言限制:Proxy 只能代理已存在的对象,而 new 操作符调用构造函数时,目标(target)必须是一个函数(或具有 [[Construct]] 内部方法的对象),且 Proxy 对该函数的代理仅能通过 construct 拦截器捕获 new 调用——但前提是这个 Proxy 本身被当作构造函数使用,即 new proxy(...)。
关键点在于:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 你不能用
Proxy去“拦截某个普通对象被new调用”,因为普通对象(如{}、Array实例外的 plain object)根本不是构造函数,没有[[Construct]],new obj()会直接抛出TypeError: obj is not a constructor; -
Proxy的construct拦截器只在proxy本身被new调用时生效,即new proxy(...),而不是new target(...)且target是个对象。
所以准确来说:
✅ 你可以用 Proxy 代理一个函数,并用 construct 拦截 new proxy(...);
❌ 你不能用 Proxy 拦截对一个普通对象(比如 { name: 'a' })的 new 调用——这语法本身就不合法,根本走不到拦截环节。
如何用 Proxy 拦截 new 调用?
你需要代理一个可构造的函数(如类、普通函数),并在 handler 中定义 `construct`:const TargetConstructor = function (name) {
this.name = name;
};
const proxy = new Proxy(TargetConstructor, {
construct(target, args, newTarget) {
console.log('new 被调用,参数:', args);
console.log('new.target:', newTarget === proxy); // true
// 必须返回一个对象(否则 TypeError)
return new target(...args);
}
});
const instance = new proxy('Alice'); // 触发 construct 拦截
console.log(instance.name); // 'Alice'
construct 拦截器的三个参数
- `target`:原始被代理的构造函数(如上面的 `TargetConstructor`); - `args`:`new` 调用时传入的参数数组(如 `['Alice']`); - `newTarget`:实际 `new` 调用时的构造器,通常是 proxy 本身(除非继承链中存在子类)。注意:construct 必须返回一个对象,否则会抛出 TypeError。
为什么不能代理普通对象并拦截 new?
因为: - `{}`、`Object.create(null)`、`{ method() {} }` 等 plain object 没有 `[[Construct]]` 内部方法; - `new {}` 语法非法,JS 引擎在解析阶段就报错,根本不会创建 Proxy 或触发任何拦截; - `Proxy` 的能力边界是“重写基本操作”,但不包括让非函数变成可构造的——那是引擎底层约束,无法绕过。替代思路:控制实例化行为
如果目标是“监控或改造某类对象的创建过程”,正确做法是: - 把类/构造函数本身代理(如上例); - 使用工厂函数封装 `new` 调用,并在工厂里加逻辑; - 利用 `class` 的 `constructor` 静态方法或私有字段做初始化控制; - 对于已有对象想“模拟构造行为”,应明确用函数包装,而非强行 `new` 一个字面量。不复杂但容易忽略:Proxy 的能力取决于 target 的类型和操作是否合法。想拦截 new,target 得先是个合法构造器。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










