You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Function.prototype.call实现ES6 class的动态继承?

问题原因说明

1. 第一种写法报错的根因

你之前对报错原因的认知存在偏差:ES6 class本质就是构造函数的语法糖,typeof Person 会返回 function,它的原型链上也确实存在Function.prototype.call方法。
报错的核心原因是 ES6规范明确规定:class构造函数仅支持通过new关键字调用,禁止作为普通函数直接执行,因此直接执行Person.call()会抛出Class constructor Person cannot be invoked without 'new'错误。

2. 第二种写法无效的原因

Person.constructor指向的是Function构造函数(因为Person本身是Function的实例),你调用Person.constructor.call(this, ...args)本质是执行了一个空的匿名函数,自然不会给当前this挂载test、name等属性。


实现方案

无需修改原有Person class的代码,可根据场景选择以下实现方式:

场景1:Police固定继承Person

直接使用ES6原生的extends + super语法即可,这是最标准的类继承实现:

class Person {
  constructor(name, test) {
    this.name = name;
    this.test = test;
  }
}
class Police extends Person {
  constructor(name, badge, ...manyArgs) {
    // 调用父类构造函数完成初始化
    super(name, 'hello world');
    this.badge = badge;
    console.log(this.test); // 输出:'hello world'
  }
}

场景2:动态继承/混入(不需要固定绑定继承关系)

如果需要在构造函数内动态调用任意class的初始化逻辑,可选两种实现:

方式1:实例化后合并属性

直接实例化目标class,将实例的自有属性合并到当前this上:

class Police {
  constructor(name, badge, ...manyArgs) {
    // 实例化Person后合并属性到当前实例
    Object.assign(this, new Person(name, 'hello world'));
    this.badge = badge;
    console.log(this.test); // 输出:'hello world'
  }
}

方式2:Reflect.construct实现底层调用

如果需要精确控制构造函数的调用上下文,可以用Reflect.construct实现类似call的绑定效果:

class Police {
  constructor(name, badge, ...manyArgs) {
    // 调用Person构造函数,指定实例原型指向当前类的原型,等同于绑定this
    const parentInstance = Reflect.construct(Person, [name, 'hello world'], new.target);
    Object.assign(this, parentInstance);
    this.badge = badge;
    console.log(this.test); // 输出:'hello world'
  }
}

内容的提问来源于stack exchange,提问作者DutchJelly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 16:06:04