ES6之前JavaScript实现面向对象编程主要依赖原型链,语法相对晦涩,ES6新增的Class语法让类的定义和继承更清晰直观,更符合传统面向对象语言的书写习惯。ES6的Class本质上是原型链的语法糖,其核心继承逻辑依然基于原型,但封装了更简洁的写法。

ES6 Class的基本定义
ES6中使用class关键字定义类,类的构造函数用constructor方法定义,类的实例方法直接写在类内部,不需要用function关键字声明。
// 定义一个基础的Person类
class Person {
// 构造函数,初始化实例属性
constructor(name, age) {
this.name = name;
this.age = age;
}
// 实例方法
sayHello() {
console.log(`你好,我是${this.name},今年${this.age}岁`);
}
// 静态方法,通过类直接调用,不依赖实例
static createPerson(name, age) {
return new Person(name, age);
}
}
// 创建实例
const person1 = new Person('张三', 20);
person1.sayHello(); // 输出:你好,我是张三,今年20岁
const person2 = Person.createPerson('李四', 25);
person2.sayHello(); // 输出:你好,我是李四,今年25岁
ES6 Class实现继承的核心语法
ES6中通过extends关键字实现类的继承,子类可以继承父类的所有属性和方法,同时可以通过super关键字调用父类的构造函数或方法。
extends关键字的使用
子类在定义时后面跟上extends 父类名即可建立继承关系,子类会自动拥有父类的实例方法和静态方法。
// 定义Student类继承Person类
class Student extends Person {
constructor(name, age, grade) {
// 调用父类构造函数,必须在使用this之前调用
super(name, age);
// 子类自己的属性
this.grade = grade;
}
// 子类自己的实例方法
study() {
console.log(`${this.name}正在上${this.grade}年级`);
}
// 重写父类的sayHello方法
sayHello() {
// 调用父类的sayHello方法
super.sayHello();
console.log(`我目前读${this.grade}年级`);
}
// 子类自己的静态方法
static createStudent(name, age, grade) {
return new Student(name, age, grade);
}
}
const student1 = new Student('王五', 18, 12);
student1.sayHello();
// 输出:
// 你好,我是王五,今年18岁
// 我目前读12年级
student1.study(); // 输出:王五正在上12年级
// 子类也能继承父类的静态方法
const student2 = Student.createPerson('赵六', 17);
student2.sayHello(); // 输出:你好,我是赵六,今年17岁
super关键字的使用规则
super在子类中有两种使用场景,使用规则有明显区别:
- 作为函数调用:
super()代表调用父类的构造函数,只能在子类的constructor中使用,且必须在使用this之前调用,否则会报错。 - 作为对象调用:
super.方法名代表调用父类的实例方法,super.静态方法名代表调用父类的静态方法,可以在子类的实例方法或静态方法中使用。
class Parent {
constructor(x) {
this.x = x;
}
printX() {
console.log(this.x);
}
static staticMethod() {
console.log('父类静态方法');
}
}
class Child extends Parent {
constructor(x, y) {
// 错误写法:先使用this再调用super
// this.y = y;
// super(x);
// 正确写法
super(x);
this.y = y;
}
printInfo() {
super.printX(); // 调用父类实例方法
console.log(this.y);
}
static childStaticMethod() {
super.staticMethod(); // 调用父类静态方法
console.log('子类静态方法');
}
}
Child.childStaticMethod();
// 输出:
// 父类静态方法
// 子类静态方法
ES6 Class继承与传统原型链继承的对比
ES6 Class继承是传统原型链继承的语法糖,两者底层逻辑一致,但写法和使用体验有明显差异:
| 对比维度 | ES6 Class继承 | 传统原型链继承 |
|---|---|---|
| 语法复杂度 | 简洁,使用extends、super关键字,逻辑清晰 | 复杂,需要手动操作prototype、constructor等属性 |
| 构造函数调用 | super()统一调用父类构造函数 | 需要手动调用父类构造函数并绑定this |
| 静态方法继承 | 自动继承父类静态方法 | 需要手动将子类prototype指向父类实例,再修正constructor |
| 父类属性初始化 | 父类构造函数逻辑自动执行 | 容易出现引用类型属性共享的问题 |
继承中的注意事项
- 子类如果没有定义
constructor方法,会默认生成一个构造函数,自动调用super(...args)并传递所有参数。 - 父类的私有属性(通过#定义的属性)子类无法直接访问,只能通过父类提供的公共方法操作。
instanceof操作符可以判断实例是否属于某个类,继承关系中实例同时属于子类和父类。
class Animal {
#privateField = '私有属性';
getPrivateField() {
return this.#privateField;
}
}
class Dog extends Animal {
// 没有定义constructor,默认生成
}
const dog = new Dog();
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(dog.getPrivateField()); // 输出:私有属性
// console.log(dog.#privateField); // 报错,无法访问父类私有属性
ES6 Class继承本质是原型链继承的封装,理解原型链的核心逻辑能更好地掌握Class继承的底层原理,遇到复杂问题时可以从原型层面排查原因。
JavaScriptES6_Class继承原型链修改时间:2026-06-26 06:30:40