标准答案
- class 是基于原型链的语法层,并不是新的继承模型。class 里的实例方法会定义在构造函数的 prototype 上,实例通过原型链访问这些方法。
- constructor 是创建实例时执行的构造函数。class 必须通过 new 调用,不能像普通函数一样直接调用;class 内部默认运行在严格模式下。
- extends 用来建立子类和父类的继承关系。子类 constructor 中必须先调用 super(),才能访问 this,因为 super() 会执行父类构造逻辑并初始化实例。
- static 定义的是类本身的方法或属性,不属于实例。实例不能直接访问 static 方法;静态方法里可以通过 super 调用父类静态方法。
题目解析
class 更像是把构造函数、prototype 方法和继承关系包装成更清晰的语法。理解 class 时仍然要回到原型链:实例方法不复制到每个实例上,而是挂在 prototype 上共享。
extends 不只连接实例原型链,也会连接子类构造函数和父类构造函数之间的继承关系。因此子类既能继承实例方法,也能通过静态继承使用父类静态成员。
super 有两个常见位置:在子类 constructor 中调用父类构造函数;在实例方法中调用父类原型方法。静态方法里的 super 则指向父类本身。
class 方法默认不可枚举,这和直接给构造函数 prototype 赋值有差异。理解这些细节有助于解释 Object.keys、for...in 为什么看不到 class 方法。
代码示例
下面例子展示 class 方法仍然位于 prototype 上,static 方法属于类本身。
JavaScript
class Animal {
constructor(name) {
this.name = name
}
speak() {
return this.name + ' makes a noise'
}
static category() {
return 'life'
}
}
class Dog extends Animal {
speak() {
return super.speak() + ', and barks'
}
}
const dog = new Dog('Lucky')
dog.speak()
Dog.category()
Object.getPrototypeOf(dog) === Dog.prototype // true
Dog.prototype.speak === dog.__proto__.speak // true常见误区
- 误以为 class 彻底脱离原型链。
- 子类 constructor 中在 super() 前访问 this。
- 把 static 方法当成实例方法调用。