




JavaScript 的 class 只是语法糖,未改变原型本质;它要求 super() 必须首行调用、不提升、方法不可枚举,继承仍基于 [[Prototype]] 链,核心在于对象创建时的原型关联、属性查找与 this 绑定。
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]])。
常见错误场景:
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;
}
}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 背后触发了哪些原型操作。