es6 中的类的继承

ES6 中 super 关键字的详细解析

在 ES6 中,super 关键字是类继承的核心组成部分。它用于调用父类的构造函数和方法。在子类继承父类时,super 的正确使用至关重要。了解如何使用 super() 来触发父类构造函数的执行,以及如何在方法中通过 super.method() 调用父类的方法,是理解 JavaScript 类和继承机制的关键。

1. super():调用父类构造函数

当子类继承父类时,子类的构造函数默认并不会执行父类的构造函数。为了确保父类的初始化逻辑被正确执行,子类必须显式调用 super() 来触发父类构造函数的执行。特别是当父类有构造函数时,super() 必须在子类构造函数中调用,否则子类无法正确继承父类的属性,且会抛出错误。

示例:不调用 super() 会出错
js 复制代码
class A {
  constructor(name) {
    this.name = name;
    console.log('A constructor');
  }
}

class B extends A {
  constructor(name, age) {
    // 如果没有调用 super(name),会导致错误
    this.age = age;
    console.log('B constructor');
  }
}

const b = new B('Alice', 25); // 错误:必须先调用 super()

运行上述代码时,将抛出如下错误:

js 复制代码
Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this'.

这是因为在子类构造函数中,必须先调用 super(),以便初始化父类的部分。这是 JavaScript 类继承中的一条规则:子类构造函数中必须先调用 super(),然后才能访问 this

2. super.method():调用父类的方法

除了在构造函数中调用 super() 以初始化父类的属性外,super 还可以在子类的方法中用于调用父类的同名方法。这对于在子类中重写父类方法时保留父类的原有逻辑非常有用。

示例:子类调用父类的方法
js 复制代码
class A {
  method() {
    console.log('A method');
  }
}

class B extends A {
  method() {
    super.method();  // 调用父类 A 的 method()
    console.log('B method');
  }
}

const b = new B();
b.method();

输出:

js 复制代码
A method
B method

在这个例子中,子类 B 重写了 method 方法,并在其中通过 super.method() 调用了父类 Amethod() 方法。这样,子类不仅执行了父类的方法,还可以添加自己的逻辑。

3. super() 在多层继承中的行为

当存在多层继承时,super() 的调用顺序会遵循继承链,从子类向上逐层调用父类的构造函数和方法。

示例:多层继承中的 super()
js 复制代码
class A {
  constructor() {
    console.log('A constructor');
  }
  method() {
    console.log('A method');
  }
}

class B extends A {
  constructor() {
    super();  // 调用 A 的构造函数
    console.log('B constructor');
  }

  method() {
    super.method();  // 调用 A 的 method()
    console.log('B method');
  }
}

class C extends B {
  constructor() {
    super();  // 调用 B 的构造函数,B 中又调用了 A 的构造函数
    console.log('C constructor');
  }

  method() {
    super.method();  // 调用 B 的 method(),B 中又调用了 A 的 method()
    console.log('C method');
  }
}

const c = new C();
c.method();

输出:

js 复制代码
A constructor
B constructor
C constructor
A method
B method
C method

在这个例子中,C 类继承了 B,而 B 又继承自 Asuper() 会依次触发每个父类的构造函数和方法。首先,C 调用 super() 触发 B 的构造函数,B 的构造函数又调用 super() 触发 A 的构造函数。然后,在调用 c.method() 时,C 调用自己的 method(),而 Bmethod() 又调用 Amethod()

4. 父类没有构造函数时的行为

如果父类没有显式定义构造函数(即默认构造函数),子类仍然需要调用 super(),尽管父类的构造函数不执行任何操作。即使没有初始化逻辑,子类仍然需要调用 super() 来确保正确的继承行为。

示例:父类没有构造函数时
js 复制代码
class A {
  // 没有显式的构造函数
}

class B extends A {
  constructor(age) {
    super();  // 必须调用 super()
    this.age = age;
    console.log('B constructor');
  }
}

const b = new B(25);

尽管 A 没有定义构造函数,子类 B 仍然需要调用 super(),以确保继承链的完整性。

总结

在 ES6 的类继承中,super() 是子类与父类之间进行交互的关键。当子类继承父类时,子类的构造函数必须显式调用 super(),否则无法访问父类的 this,并且会导致错误 。通过 super.method(),子类可以调用父类的方法,继承父类的行为,并在此基础上进行扩展。对于多层继承,super() 会依次触发每一层父类的构造函数和方法。

理解和正确使用 super() 是实现类继承和子类扩展父类功能的基础。

相关推荐
郭老二7 小时前
【前端】vue3:编译步骤
前端
不在逃避q8 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁8 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9858 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易8 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师9 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户0595401744610 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈10 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen11 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒11 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端