JavaScript无class语法时如何调用强制要求new的父构造函数
问题根源
你惯用的ES5继承写法仅适配老式构造函数:这类构造函数不校验调用方式,且会直接在传入的this对象上挂载属性。但ES6新增的内置类(如MediaSource)、所有用class定义的构造函数都带有[[IsClassConstructor]]内部标记:
- 禁止通过
.call()/.apply()的方式非new调用,直接调用会抛出你遇到的'new' is required错误 - 不会使用你传入的自定义
this对象,必须由构造函数本身生成带合法内部槽的实例
这就是老写法失效的核心原因。
无class语法的正确实现(等价于class的super()逻辑)
ES6 class语法中super()的本质逻辑是:调用父类构造生成合法实例,同时将实例的原型绑定到当前子类的prototype,替换掉子类构造时默认生成的空this对象。不用class语法时,可通过Reflect.construct()实现完全一致的效果,这也是super()的底层实现逻辑:
// 第一步:正确设置原型链,修正constructor指向 MyClass.prototype = Object.create(Class.prototype, { constructor: { value: MyClass, enumerable: false, writable: true, configurable: true } }); function MyClass() { // 等价于class语法中的 super(...arguments) // 第三个参数指定实例的原型绑定到当前调用的子类(支持子类继续继承MyClass的场景) const _this = Reflect.construct(Class, arguments, new.target || MyClass); // 子类自定义的属性、初始化逻辑全部挂载到_this上 _this.customAttr = '子类自定义属性'; // 必须返回_this,替换new MyClass时默认生成的空对象 return _this; } // 原型方法可正常生效 MyClass.prototype.customMethod = function() { console.log(this.customAttr); }; // 实例化验证 const myInstance = new MyClass(/* 传入父类构造需要的参数 */); myInstance.customMethod(); // 正常输出 console.log(myInstance instanceof MyClass); // true console.log(myInstance instanceof Class); // true
你之前尝试的
new Class()方案的缺陷 你想到的手动new Class()后返回实例的写法,问题在于生成的实例原型固定指向Class.prototype,没有关联到MyClass.prototype,自然无法访问你在MyClass原型上定义的属性和方法。Reflect.construct的第三个参数就是专门用来指定实例原型对应的构造函数,刚好解决这个问题:生成的实例既带父类要求的所有内部合法槽位,原型链也完全符合继承预期。
注意:如果要兼容不存在
ReflectAPI的极老运行环境(如IE11),没有方案可以完美继承这类ES6内置类。这类内置类的实例带有无法手动挂载的特殊内部槽,必须通过构造函数本身生成合法实例,这也是class语法成为ES6之后继承内置类标准方案的原因。
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

