JavaScript 的 class 只是语法糖,未改变原型本质;它要求 super() 必须首行调用、不提升、方法不可枚举,继承仍基于 [[Prototype]] 链,核心在于对象创建时的原型关联、属性查找与 this 绑定。

JavaScript 里 class 不是“新类型”,只是语法糖
ES6 的 class 关键字没有改变 JavaScript 基于原型的本质。它只是把原本用 function + prototype 写的构造逻辑,包装成更接近传统 OOP 语言的写法。如果你试图用 Java/C# 的类模型去套,很容易在动态性、this 绑定、继承链这些地方掉坑。
实操建议:
-
class声明不会被提升(hoisted),必须先声明再使用,否则报ReferenceError - 类体内只能写方法定义、
get/set、static成员,不能写普通变量或表达式 - 所有方法默认不可枚举(
enumerable: false),这点和手动挂到prototype上一致 - 类内部不支持私有字段语法(如
#private)在旧环境会直接报错,需确认目标运行时是否支持
用 extends 和 super() 实现继承时,super() 必须调用
子类构造函数中若定义了 constructor,就必须显式调用 super(),否则会报 ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor。这不是可选项,是引擎强制的时序约束——因为子类实例的 this 依赖父类构造器初始化内部槽位(如 [[Prototype]])。
常见错误场景:
立即学习“Java免费学习笔记(深入)”;
- 只写了
super()但没传参,导致父类接收不到必要参数 - 在
super()前访问this,哪怕只是console.log(this)也会立即报错 - 误以为
super.method()等价于Parent.prototype.method.call(this),其实前者在箭头函数中会丢失this绑定上下文
示例:
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // ✅ 必须且必须在第一行
this.breed = breed;
}
}原型链继承 vs 类继承:关键差异在 instanceof 和 Object.getPrototypeOf()
用 class 定义的继承,底层仍靠修改 [[Prototype]] 链,所以 instanceof 和 Object.getPrototypeOf() 的行为和手写原型链一致。但有个易忽略点:子类的 constructor 属性默认指向自身,而它的 prototype 对象的 constructor 会被自动设为子类——这个自动修正只发生在 class 语法中,手动操作 prototype 时得自己补。
影响实际开发的细节:
- 用
new Dog()创建的实例,Object.getPrototypeOf(new Dog()) === Dog.prototype,而Object.getPrototypeOf(Dog.prototype) === Animal.prototype - 如果子类重写了静态方法,比如
static create(),它不会自动调用父类同名静态方法,必须显式写super.create() - 子类无法直接继承父类的实例属性(如
this.id = Math.random()),只能通过super()触发父类构造器执行来获得
真正需要关注的不是“怎么写类”,而是“对象创建时发生了什么”
JavaScript 面向对象的核心从来不是语法,而是三件事:对象如何关联原型、属性查找如何沿链进行、方法调用时 this 如何绑定。类语法掩盖了这些过程,反而容易让人忽略 Object.create(null)、Object.setPrototypeOf()、Reflect.construct() 这些底层机制的存在价值。
比如你遇到以下情况,就得跳出 class 思维:
- 需要创建一个无原型的对象(避免继承
Object.prototype方法) - 运行时动态改变某个实例的原型(
__proto__已废弃,该用Object.setPrototypeOf()) - 想让构造函数返回非默认对象(比如缓存已有实例),这时
class语法完全不支持,必须退回普通函数
复杂点不在语法多难记,而在你是否清楚每个 new、extends、super 背后触发了哪些原型操作。










