如何用class语法扩展JavaScript旧式function类?
解决Function类继承ES6 Class类的构造函数调用问题
ES6 Class的构造函数强制要求通过new关键字调用,不能像普通函数那样用call/apply绑定this执行,这就是出现Uncaught TypeError: Class constructor NewBase cannot be invoked without 'new'错误的核心原因。以下是几种无需大幅重构原有代码的解决方案:
方案1:使用Reflect.construct调用Class构造函数
这是无需修改NewBase和OldClass结构的最优方案,通过Reflect.construct模拟new的行为,同时将构造函数的上下文绑定到OldClass实例的this上:
class NewBase { constructor() { this.value = 'NewBase'; } fromOldBase() { return 'from: ' + this.value; } } const OldClass = function() { // 用Reflect.construct调用NewBase构造函数,绑定当前this // 第三个参数指定new.target,确保Class内的相关逻辑正常工作 Reflect.construct(NewBase, [], new.target || OldClass); }; Object.setPrototypeOf(OldClass.prototype, NewBase.prototype); OldClass.prototype.constructor = OldClass; const x = new OldClass(); console.log(x.fromOldBase()); // 输出: from: NewBase
Reflect.construct的第三个参数用于设置new.target,如果是通过new OldClass创建实例,new.target就是OldClass,添加默认值OldClass是为了兼容直接调用OldClass()的极端情况(不推荐这么做)。
方案2:给Class拆分初始化方法(备选)
如果允许给NewBase添加一个初始化方法,把构造函数内的逻辑移到这个方法里,就可以在OldClass中通过call绑定this调用:
class NewBase { constructor() { this.init(); } // 拆分初始化逻辑到独立方法 init() { this.value = 'NewBase'; } fromOldBase() { return 'from: ' + this.value; } } const OldClass = function() { NewBase.prototype.init.call(this); }; Object.setPrototypeOf(OldClass.prototype, NewBase.prototype); OldClass.prototype.constructor = OldClass; const x = new OldClass(); console.log(x.fromOldBase()); // 输出: from: NewBase
不过正如你所说,这种方式的必要性不如直接重构NewBase。
方案3:重构NewBase为Function类(最直接)
既然你提到重构NewBase比重构OldClass容易,直接将NewBase转为传统Function类是最直观的解决方式,完全兼容原有OldClass的继承写法:
const NewBase = function() { this.value = 'NewBase'; }; NewBase.prototype.fromOldBase = function() { return 'from: ' + this.value; }; const OldClass = function() { NewBase.call(this); }; Object.setPrototypeOf(OldClass.prototype, NewBase.prototype); OldClass.prototype.constructor = OldClass; const x = new OldClass(); console.log(x.fromOldBase()); // 输出: from: NewBase
内容的提问来源于stack exchange,提问作者TheJim01
相关产品推荐
相关产品推荐

