ES6 class 是语法糖,本质仍是原型链继承,所有继承基于[[Prototype]]链,class声明编译为构造函数并自动设置prototype和constructor,extends通过Object.setPrototypeOf实现继承。
class 只是语法糖,底层仍是原型链继承它没有改变 JavaScript 的继承机制本质——所有继承依然基于 [[Prototype]] 链。所谓“类”,只是把原本用 function + prototype + Object.setPrototypeOf 手动搭的结构,包装成更接近传统 OOP 语言的写法。
真正执行时,class 声明会被编译为构造函数,并自动设置 prototype 和 constructor 属性;extends 则会调用 Object.setPrototypeOf(SubClass, SuperClass) 和 Object.setPrototypeOf(SubClass.prototype, SuperClass.prototype)。
class 内部方法默认不可枚举(比手写 prototype 更干净)class 声明不会被提升(而函数声明会),且必须用 new 调用,否则报 TypeError: Class constructor X cannot be invoked without 'new'
prototype 或构造函数本身挂载,没新增任何底层机制class 并实现继承?关键在三步:定义基类、用 extends 继承、子类中必须调用 super()(哪怕不传参)。
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound.`;
}
}
cl
ass Dog extends Animal {
constructor(name, breed) {
super(name); // ← 必须!否则报 ReferenceError
this.breed = breed;
}
speak() {
return `${this.name} barks.`;
}
}
constructor 时,子类会自动获得默认构造函数:constructor(...args) { super(...args); }
super() 必须在访问 this 之前调用,否则报 ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Dog.isAnimal = true 不会覆盖从 Animal 继承来的 isAnimal,但可通过 static get isAnimal() { return true; } 显式定义instanceof 和 Object.getPrototypeOf 仍能准确反映真实关系?因为 class 没有绕过原型系统,只是让原型链更“规整”。你可以用原生 API 验证它的底层结构:
const dog = new Dog('Max', 'Golden');
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
Dog.prototype.__proto__ 指向 Animal.prototype(尽管不推荐直接用 __proto__)Dog.__proto__ 指向 Animal,这决定了静态属性/方法的继承链Dog.prototype(比如赋值为新对象),会断开与 Animal.prototype 的连接,instanceof 就会失效new.target 和装饰器兼容性ES6 class 本身不支持私有成员,直到 ES2025 才加入 #field 语法;而 new.target 在 class 构造器中行为更严格——它能区分是否被 new 调用,这对编写可继承的工具类很关键。
#name 是真正的私有(无法被子类访问),不是命名约定(如 _name)new.target 在基类构造器中指向实际被 new 的类(比如 new Dog() 时,new.target === Dog),可用于防止类被直接实例化@bound)依赖 Babel 或 TypeScript 转译,原生 class 不支持运行时装饰,这点常被误认为是“类的限制”真正复杂的地方在于:你得同时理解语法糖表象和原型链实质。一旦遇到奇怪的 instanceof 失败、this 绑定异常或继承链断裂,问题几乎总出在原型操作被意外覆盖,而不是 class 本身。