es6类继承

ES6 类继承:从原型链到现代语法糖的进化

1. ES6 类继承基本语法

1.1 类声明与继承

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);  // 必须首先调用!
    this.breed = breed;
  }

  bark() {
    console.log(`${this.name} (${this.breed}) barks: Woof!`);
  }

  // 方法重写
  speak() {
    super.speak();  // 调用父类方法
    console.log('And also wags tail');
  }
}

1.2 关键特性

  • extends 建立继承关系
  • super 在构造函数和方法中的不同表现
  • 方法自动绑定 [[HomeObject]](底层实现)

2. 继承链的构建原理

2.1 原型链结构

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 静态属性继承
Object.setPrototypeOf(Dog, Animal);

2.2 实例化过程

  1. 创建新对象,关联子类原型
  2. 执行子类构造函数
  3. 通过 super() 激活父类构造函数
  4. 完成实例属性初始化

3. super 的运行时机制

3.1 构造函数中的 super

  • 必须在使用 this 前调用
  • 相当于 Animal.prototype.constructor.call(this, ...args)

3.2 方法中的 super

// 以下两种写法等价
super.method();
Object.getPrototypeOf(Dog.prototype).method.call(this);

4. 静态成员的继承

class Base {
  static version = '1.0';
  static logVersion() {
    console.log(this.version);
  }
}

class Sub extends Base {
  static version = '2.0';
}

Sub.logVersion();  // 输出 "2.0"

特性:

  • 静态方法通过 super.constructor 访问父类
  • 遵循与实例方法不同的继承链

5. 与 ES5 实现的对比

5.1 传统实现方式

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a noise.');
};

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

5.2 ES6 的优势对比

特性ES5ES6
代码可读性低(显式操作原型链)高(类语法)
静态继承需手动实现自动继承
方法重写容易破坏原型链super 安全访问
内置类扩展不可靠规范支持

6. 开发实践与注意事项

6.1 强制规范

  1. 子类构造函数必须优先调用 super()
  2. 禁止在 super() 前访问 this
  3. 方法中的 super 基于静态绑定

6.2 高级模式

扩展内置类型

class CustomError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
    this.name = 'CustomError';
  }
}

抽象类模式

class AbstractClass {
  constructor() {
    if (new.target === AbstractClass) {
      throw new Error('Cannot instantiate abstract class');
    }
  }
}

6.3 常见错误示例

class Buggy extends Animal {
  constructor() {
    this.prop = 123; // 报错:Must call super constructor first
    super();
  }
}

7. 示例

以下是一个完整的 ES6 类继承示例,包含方法重写、super 使用和静态方法继承:

// 基类:电子设备
class ElectronicDevice {
  static powerType = 'electricity'; // 静态属性

  constructor(brand) {
    this.brand = brand;
    this.isOn = false;
  }

  // 实例方法
  togglePower() {
    this.isOn = !this.isOn;
    console.log(`${this.brand} device is now ${this.isOn ? 'ON' : 'OFF'}`);
  }

  // 静态方法
  static describePower() {
    console.log(`All devices use ${this.powerType}`);
  }
}

// 子类:智能手机
class Smartphone extends ElectronicDevice {
  static powerType = 'battery'; // 重写静态属性

  constructor(brand, os) {
    super(brand); // 必须首先调用父类构造函数!
    this.operatingSystem = os;
    this.battery = 100;
  }

  // 方法重写 + 扩展
  togglePower() {
    if (this.battery <= 0) {
      console.log('Battery dead!');
      return;
    }
    super.togglePower(); // 调用父类方法
  }

  // 新增方法
  checkBattery() {
    console.log(`${this.brand} ${this.operatingSystem} phone: ${this.battery}%`);
  }

  // 重写静态方法
  static describePower() {
    super.describePower(); // 调用父类静态方法
    console.log(`(Specifically smartphones use ${this.powerType})`);
  }
}

// 使用示例
const iphone = new Smartphone('Apple', 'iOS');

iphone.togglePower(); 
// 输出: Apple device is now ON
// 执行了父类和子类的组合逻辑

iphone.checkBattery(); 
// 输出: Apple iOS phone: 100%

Smartphone.describePower();
// 输出:
// All devices use battery 
// (Specifically smartphones use battery)

// 静态属性继承演示
console.log(ElectronicDevice.powerType); // electricity
console.log(Smartphone.powerType);       // battery

关键知识点解释:

  1. 继承链构建
  • Smartphone.prototype 继承自 ElectronicDevice.prototype
  • Smartphone 类本身继承自 ElectronicDevice 类(静态成员继承)
  1. 方法重写机制
  • 子类中定义同名方法会覆盖父类方法
  • 通过 super.methodName() 可以调用父类原始方法
  1. 静态成员继承
  • 静态属性和方法也会被继承
  • 子类可以重写父类的静态成员
  • 通过 super.staticMethod() 调用父类静态方法
  1. 构造函数要求
  • 子类构造函数必须先调用 super()
  • 之后才能使用 this 关键字
  1. 原型链验证
console.log(iphone instanceof Smartphone);    // true
console.log(iphone instanceof ElectronicDevice); // true

结语:面向未来的类设计

ES6 类继承通过规范化语法:

  1. 降低原型链的理解门槛
  2. 提升代码可维护性
  3. 支持更严谨的 OOP 模式
  4. 为静态类型系统(TypeScript)奠定基础

在实际工程中,建议结合 private 字段(ES2022)和装饰器提案,构建健壮的类层次结构。对于复杂场景,可考虑组合模式(composition)与类继承的配合使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王小玗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值