reflect.construct 可在不使用 new 的前提下模拟构造函数调用,并动态指定新实例的 [[prototype]]。其语法为 reflect.construct(target, args, newtarget),其中 newtarget 决定实例的原型链指向;若 newtarget 为非构造函数但含 prototype 属性,则实例直接继承该 prototype;还可结合 object.setprototypeof 进一步调整原型。

Reflect.construct 可以在不使用 new 关键字的前提下,模拟构造函数调用,并支持**动态指定新实例的原型链(即 [[Prototype]])**,这是它区别于 new 的关键能力。
核心用法:传入 target、args 和可选的 newTarget
标准语法为:Reflect.construct(target, argumentsList[, newTarget])
其中:
- target 是要调用的构造函数;
- argumentsList 是传给构造函数的参数数组;
- newTarget 是可选参数,用于指定新实例的 [[Prototype]] 指向(即 constructor.prototype 的来源)。
当提供 newTarget 时,新实例的 __proto__(内部 [[Prototype]])将指向 newTarget.prototype,而不是 target.prototype —— 这就是“动态改变原型链”的本质。
如何让实例继承自自定义原型对象
你可以传入一个**非构造函数但拥有 prototype 属性的对象**作为 newTarget,从而让实例直接链接到你指定的原型:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 确保
newTarget是一个函数(哪怕空函数),或至少有prototype属性; - 该
prototype对象将成为新实例的直接原型; - 如果
newTarget不是函数,会抛出TypeError(因为规范要求newTarget必须是构造器或具有prototype的对象)。
示例:
function A() {}
A.prototype.foo = 'from A';
<p>function B() {}
B.prototype.bar = 'from B';</p><p>const instance = Reflect.construct(A, [], B); // 用 A 构造,但原型链指向 B.prototype
console.log(instance.bar); // 'from B'
console.log(instance.foo); // undefined(没继承 A.prototype)
console.log(Object.getPrototypeOf(instance) === B.prototype); // true</p>
配合 Object.setPrototypeOf 实现更灵活的原型控制
Reflect.construct 本身只决定初始 [[Prototype]],但若需进一步调整(比如替换为纯对象、或绕过函数限制),可结合 Object.setPrototypeOf:
- 先用
Reflect.construct创建实例(哪怕用默认newTarget); - 再用
Object.setPrototypeOf(instance, yourProto)显式重设原型; - 注意:该方法会修改已有实例,且某些环境(如严格模式下冻结对象)可能失败。
例如:
const objProto = { custom: true };
const inst = Reflect.construct(A, []);
Object.setPrototypeOf(inst, objProto);
console.log(inst.custom); // true
实际应用场景
这种能力常用于:
- 实现更安全的“代理构造”(如拦截实例化过程);
- 构建兼容不同类体系的适配器实例;
- 单元测试中模拟特定原型行为;
- 序列化/反序列化时还原带自定义原型的对象。
注意:Reflect.construct 不会触发 new.target 的常规行为(除非显式传入 newTarget),且无法绕过构造函数内部对 this 的硬编码逻辑(如强制检查 instanceof)。所以它适合控制原型链,但不能完全替代构造函数语义。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










