JavaScript ES6为何无法调用匿名super函数?类与匿名函数父子关系解析
嘿,我来帮你拆解这两个问题,结合你的案例把逻辑讲清楚:
问题1:为什么JavaScript ES6无法调用匿名super函数?
你这里说的“匿名super函数”其实是指类字段定义的箭头函数(比如案例2里的exec = () => {})。问题的核心在于super的工作机制和箭头函数的挂载方式不匹配:
super关键字在类的方法中,指向的是父类的原型对象(也就是Parent.prototype)。但案例2里的exec并不是挂载在父类的原型上,而是作为实例属性存在的——当你用exec = () => {}这种类字段语法时,这个函数会在每个实例创建时被赋值到实例本身,而不是Parent.prototype上。
所以当子类里写super.exec()时,JavaScript会去Parent.prototype里找exec方法,但父类的exec根本不在原型上,结果就是super.exec是undefined,调用undefined()自然会抛出TypeError,这就是你看到“无输出、疑似崩溃”的原因——代码在执行super.exec()时就报错终止了,后面的console.log根本没机会运行。
问题2:匿名函数(类字段箭头函数)与类函数(原型方法)实现类父子关系的差异?
直接对比两种写法的核心差异:
- 挂载位置不同
- 类函数(案例1的写法):挂载在类的
prototype对象上,所有实例共享同一个函数副本,节省内存。 - 箭头函数类字段(案例2的写法):作为实例自身的属性存在,每个新实例都会创建一个新的函数副本。
- 类函数(案例1的写法):挂载在类的
- this指向的绑定方式不同
- 类函数的
this是动态绑定的,取决于函数的调用者(比如c.exec()里的this就是实例c)。 - 箭头函数的
this是词法绑定的,定义时就绑定了当前类的实例,不会被调用方式改变。
- 类函数的
- super的访问能力不同
- 类函数可以通过
super访问父类原型上的方法,因为super指向父类原型,而父类的类函数正好在原型上。 - 箭头函数类字段无法通过
super访问父类的同名箭头函数——因为父类的箭头函数不在原型上,super找不到它。
- 类函数可以通过
- 继承与重写的行为不同
- 类函数的重写:子类重写父类的原型方法后,还能通过
super.方法名()调用父类的原始方法(比如案例1的正常执行)。 - 箭头函数类字段的重写:子类的同名箭头函数会直接覆盖父类实例上的同名属性,而且无法通过
super回溯到父类的那个函数,因为它不在父类原型上。
- 类函数的重写:子类重写父类的原型方法后,还能通过
结合你的案例再梳理
案例1(运行符合预期)
class Parent { constructor(name) { this.name = name; } exec() { console.log('name', this.name); } } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } exec() { super.exec(); console.log('age', this.age); } } const c = new Child('ChildName', 31); c.exec(); // 输出ChildName + 31(符合预期)
这里Parent和Child的exec都是原型方法,Child.exec里的super.exec()能正确找到Parent.prototype.exec,所以先输出name ChildName,再输出age 31,完全符合预期。
案例2(无输出,疑似崩溃)
class Parent { constructor(name) { this.name = name; } exec = () => { console.log('name', this.name); } } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } exec = () => { super.exec(); console.log('age', this.age); } } const c = new Child('ChildName', 31); c.exec(); // 无输出,疑似崩溃
这里Parent的exec是实例属性,Child的exec也是实例属性。当执行c.exec()时,先尝试调用super.exec(),但super指向Parent.prototype,上面没有exec方法,所以抛出TypeError: super.exec is not a function,代码直接终止,自然没有任何输出。
内容的提问来源于stack exchange,提问作者Recipe

