菜单

相关源文件

本文档涵盖了 JavaScript 中类设计的最佳实践。它详细介绍了如何使用现代 JavaScript 语法创建和构建类,何时使用某些模式,以及如何使基于类的代码更清晰、更易于维护。

有关特定对象组合模式的信息,请参阅 组合与继承

JavaScript 类简介

ES2015 (ES6) 引入的 JavaScript 类为创建对象和处理继承提供了更清晰、更直观的语法。尽管 JavaScript 在底层使用基于原型的继承模型,但类语法提供了一种更熟悉的对象蓝图定义方式,特别是对于来自面向类语言的开发者来说。

本文档概述了在 JavaScript 中使用类创建清晰、可维护代码的最佳实践。

来源: README.md1141-1377

ES2015/ES6 类与 ES5 函数构造函数对比

现代 JavaScript 类相比旧的构造函数模式,在可读性和可维护性方面具有显著优势。

为何偏爱 ES6 类

ES6 类提供了

  • 更清晰的继承语法,带有 extends
  • 标准化的构造函数方法
  • 更易读的方法定义
  • 通过 super() 进行正确的函数绑定
  • 更简洁的原型继承方式

类结构比较

来源: README.md1144-1226

示例对比

README 文件提供了 ES5 构造函数和 ES6 类在创建继承链方面的对比。ES5 版本需要冗长的代码和手动设置原型链,而 ES6 版本则更为简洁。

ES5 构造函数需要

  • 手动构造函数检查 (if (!(this instanceof...)))
  • 显式原型链配置
  • 冗长的继承设置
  • 手动调用父构造函数

ES6 类通过以下方式简化

  • 简洁的 classextends 语法
  • 内置的构造函数方法
  • 简单的 super() 用于父类初始化
  • 在类主体中定义方法

来源: README.md1152-1224

方法链式调用

方法链(Method chaining)是一种模式,可以在同一个对象上按顺序调用多个方法,从而创建更具表达力、更简洁的代码。

实现方法链

实现方法链的关键在于,在修改对象状态的方法中返回对象实例(this)。

方法链实现模式

  1. 创建修改对象状态的方法
  2. 在每个方法末尾返回 this
  3. 使用点号(dot notation)链式调用方法

来源: README.md1229-1306

方法链的优势

  • 更具表现力的代码,读起来像句子
  • 通过消除重复的对象引用来减少冗余
  • 更清晰的构建者模式(builder patterns)实现
  • 提高顺序操作的代码可读性

README 中的 Car 类示例演示了方法链如何将多个独立的调用转换为单个流畅的表达式。

来源: README.md1231-1304

组合优于继承

最重要的类设计原则之一是在大多数情况下偏爱组合而非继承。

方法比较

来源: README.md1309-1377

何时使用继承

根据清晰代码指南,在以下情况下继承是合适的:

  1. 你有一个“is-a”(是一个)关系(而不是“has-a”(有一个)关系)
  2. 基类的代码可以被派生类重用
  3. 通过更改基类,应该对派生类进行全局更改

README 文件提供了一个滥用继承的例子(Employee 和 EmployeeTaxData),因为税收数据是员工“拥有的”,而不是员工“是”的。

来源: README.md1319-1326

通过组合实现

通过组合

  • 为特定关注点创建专门的类
  • 在主类中包含这些专门类的实例
  • 将操作委托给组合的对象
  • 避免深度继承层次结构

README 中的 Employee 示例展示了如何通过创建单独的 EmployeeTaxData 类并在 Employee 类中包含其实例,从而从继承模型重构为组合模型。

来源: README.md1355-1374

类设计最佳实践

保持类小巧且专注

与函数类似,类也应该遵循 SOLID 中的单一职责原则 (SRP)。每个类应该只有一个修改的理由。

避免深度继承层次结构

深度继承层次结构可能导致

  • 脆弱的代码,在基类更改时会中断
  • 难以理解类的完整行为
  • 层次结构中的类之间高度耦合

偏爱小方法

类中的方法应遵循与函数相同的原则

  • 只做一件事
  • 保持小巧
  • 拥有描述性的名称

恰当使用访问模式

JavaScript 现在支持使用 # 前缀的私有字段。考虑

  • 将字段设为私有,当它们是实现细节时
  • 使用方法提供对状态的可控访问
  • 暴露最小化的公共 API

来源: README.md1141-1377

与 SOLID 原则的关系

JavaScript 中的类应该遵守 SOLID 原则,这些原则在第 6 部分有更详细的介绍。特别是

  • 单一职责原则:类应该只有一个修改的理由
  • 开闭原则:类应该是对扩展开放的,对修改关闭的
  • 里氏替换原则:子类应该能够被替换为其基类
  • 接口隔离原则:类不应被强制实现它们不使用的接口
  • 依赖倒置原则:依赖于抽象,而不是具体实现

通过多态(Airplane 子类)避免条件语句的示例,演示了如何将其中一些原则应用于类设计。

来源: README.md1379-1828