Reflect.construct 是 ES6 提供的唯一能正确继承内置类(如 Array、Error)的机制,它真实触发[[Construct]]内部方法以初始化内部槽,确保实例具备完整行为。

Reflect.construct 是 ES6 引入的底层构造函数调用机制,它能精确模拟 new 行为,包括设置 this、执行原型链绑定、触发 [[Construct]] 内部方法——这对继承内置类(如 Error、Array、Date)至关重要。因为直接用 Object.setPrototypeOf 或普通 call/apply 无法正确初始化内置类的内部槽(internal slots),导致实例缺少关键行为(比如 Array.isArray(arr) === false、err.stack 不生效等)。
为什么不能用传统寄生组合继承?
传统方式(如先 Parent.call(this),再 Object.setPrototypeOf(this, Child.prototype))对内置类失效,原因有三:
- 内置构造函数(如
Array)要求必须通过new调用才能初始化内部状态(如[[ArrayLength]]槽);仅Array.apply(this, args)不会触发该逻辑 -
Error实例的stack属性在构造时生成,且与this的构造调用栈强绑定;非new方式创建的对象无法获得有效堆栈 - 原型链虽可手动修复,但内部槽缺失会导致方法行为异常(例如
arr.push()可能不更新长度,err.toString()返回空字符串)
Reflect.construct 的核心用法
它接受三个参数:target(构造函数)、argsList(参数数组)、newTarget(可选,指定 new.target 值)。关键在于:它会真实执行内置类的 [[Construct]] 过程,并返回一个具备完整内部状态的实例。
要实现寄生组合继承,需分两步:
- 用
Reflect.construct(BuiltIn, args, Child)创建一个以Child为new.target的内置类实例(此时this已是正确初始化的Array或Error对象) - 在该实例上添加子类自定义属性/方法,再显式设置其原型为
Child.prototype(因Reflect.construct默认返回newTarget.prototype,但若newTarget未正确定义prototype,需手动补全)
实战:继承 Array 的自定义类
以下是一个可正确通过 Array.isArray、支持所有原生方法、且拥有自定义方法的子类:
class MyArray extends Array {
constructor(...args) {
// ✅ 正确:用 Reflect.construct 让 Array 初始化 this
const instance = Reflect.construct(Array, args, new.target);
// ✅ 设置自定义属性(this 已是真实 Array 实例)
instance.customFlag = true;
return instance;
}
customMethod() {
return 'from MyArray';
}
}
注意:必须传 new.target 作为第三个参数,否则 instance.constructor 会指向 Array 而非 MyArray,破坏 instanceof 和静态方法继承。
实战:继承 Error 的自定义错误类
这是唯一能保证 stack 正确、name 可设、且 instanceof 成立的方式:
class ValidationError extends Error {
constructor(message) {
// ✅ 必须用 Reflect.construct + new.target
const instance = Reflect.construct(Error, [message], new.target);
// ✅ 修正 name(Error 构造后 name 默认为 'Error')
instance.name = 'ValidationError';
// ✅ 添加自定义字段
instance.code = 'VALIDATION_FAILED';
return instance;
}
}
验证:const err = new ValidationError('bad input'); → err instanceof ValidationError 为 true,err.stack 包含正确调用位置,err.name 是 'ValidationError',err.code 存在。
注意事项与边界情况
使用 Reflect.construct 实现内置类继承时需牢记:
- 子类必须有
constructor,且不能省略return;不能依赖隐式返回(否则得到的是普通对象) -
new.target在箭头函数或普通函数中不可用,必须在class构造器内使用 - 若目标内置类不支持子类化(极少数旧环境),
Reflect.construct会抛出TypeError;现代浏览器和 Node.js ≥ 6.0 均支持Error、Array、Date、RegExp等的子类化 - 不要试图在
Reflect.construct后再调用Object.setPrototypeOf(instance, Child.prototype)—— 它通常已正确,强行覆盖可能破坏内置行为

















