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

学习JavaScript类时遇报错:Class constructor Hero cannot be invoked without 'new'

搞定 "Uncaught TypeError: Class constructor Hero cannot be invoked without 'new'" 报错

嘿,这个问题我太熟了!咱们来一步步拆解:

为啥会报错?

核心问题出在ES6类的构造函数规则上——它必须用new关键字调用,绝对不能像普通构造函数那样用call/apply直接执行。你在Mage这个普通函数里写Hero.call(this, name, level),相当于直接把类的构造函数当普通函数来调用,JS引擎直接给你抛出错误,告诉你“这玩意儿必须用new才行”。

而你把Hero改成普通函数构造器时,它本质就是个普通函数,没有这个调用限制,所以call能正常绑定上下文,把父类属性挂载到Mage实例上,自然就不报错了。

正确的解决姿势(ES6类标准写法)

既然用了ES6的class来定义Hero,那继承就用ES6的extends和super就好,这是官方推荐的类继承方式,代码也更清晰:

class Hero {
  constructor(name, level) {
    this.name = name
    this.level = level
  }
  greet() {
    return `${this.name} says hello.`
  }
}

// 用extends继承Hero,Mage就成了Hero的子类
class Mage extends Hero {
  constructor(name, level, spell) {
    // super必须在this之前调用,用来初始化父类的属性
    super(name, level)
    // 再添加子类自己的属性
    this.spell = spell
  }
}

// 测试一下
const merlin = new Mage('Merlin', 20, 'Fireball')
console.log(merlin.greet()) // 输出 Merlin says hello.
console.log(merlin.spell) // 输出 Fireball

非要用函数式构造器配合ES6类?(不推荐,但给个方案)

如果因为某些特殊场景,你必须保留Mage作为普通函数构造器,那可以用Reflect.construct来模拟new的调用过程,绕开类构造函数的调用限制:

class Hero {
  constructor(name, level) {
    this.name = name
    this.level = level
  }
  greet() {
    return `${this.name} says hello.`
  }
}

function Mage(name, level, spell) {
  // 用Reflect.construct调用Hero构造器,同时绑定Mage为实例的原型
  const heroInstance = Reflect.construct(Hero, [name, level], Mage)
  heroInstance.spell = spell
  return heroInstance
}

// 测试
const gandalf = new Mage('Gandalf', 30, 'Lightning')
console.log(gandalf.greet()) // Gandalf says hello.
console.log(gandalf instanceof Hero) // true
console.log(gandalf instanceof Mage) // true

不过说实话,这种写法有点绕,除非真的有必要,不然还是用extends的标准写法更省心。

内容的提问来源于stack exchange,提问作者Antonio Pavicevac-Ortiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:41:43