导入
多值引用属性
让我们学习如何实现多值引用属性。
引言
单向非功能关联可以是“一对多”或“多对多”关系。在这两种情况下,这种关联都通过多值引用属性来表示或实现。
在本章中,我们将学习:
- 从包含多值引用属性的面向对象类模型中推导出 JavaScript 类模型,这些属性用于表示单向非功能关联。
- 将 JS 类模型以 JavaScript 模型类的形式进行编码。
- 基于模型代码编写视图和控制器代码。
实现多值引用属性
多值引用属性(如 Book::authors)允许我们存储对某种类型对象(例如 Author 对象)的多个引用集合。当我们创建一个 Book 类型的新对象时,构造函数需要一个参数来提供该属性的合适值。我们可以允许该值为内部对象引用的集合,也可以是 ID 引用的集合,如下例所示:
1class Book { 2 constructor({ isbn, title, year, authors, authorIdRefs, 3 publisher, publisher_id }) { 4 this.isbn = isbn; 5 this.title = title; 6 this.year = year; 7 // 选择对象引用或 ID 引用 8 this.authors = authors || authorIdRefs; 9 if (publisher || publisher_id) this.publisher = publisher || publisher_id; 10 } 11 ... 12}
构造函数的参数记录中应包含 authors 或 authorIdRefs 之一。JavaScript 表达式 authors || authorIdRefs 使用逻辑或运算符 ||,如果存在名为 authors 的字段,则返回 authors 对象;否则返回 authorIdRefs 数组。为了处理属性设置器中的这种歧义,我们需要检查传入参数的类型,如下代码片段所示:
1set authors(a) { 2 this._authors = {}; 3 if (Array.isArray(a)) { // ID 引用数组 4 for (let idRef of a) { 5 this.addAuthor(idRef); 6 } 7 } else { // ID 引用到对象引用的映射 8 for (let idRef of Object.keys(a)) { 9 this.addAuthor(a[idRef]); 10 } 11 } 12}
JavaScript 可以通过以下两种方式实现集合类型的引用属性:
- 使用对象引用的数组列表(即 JS 数组)作为其值。
- 使用映射(map)作为其值,将对象的标准 ID 属性值作为键,映射到内部 JS 对象引用。
我们倾向于使用映射来实现集合型(set-valued)引用属性,因为它们能保证每个元素唯一。虽然也可以使用数组并手动去重,但映射中的元素可通过 delete 操作符轻松删除。而数组删除元素则需要更多操作。另一方面,对于需要保持顺序(或允许重复)的关联端(对应有序集合或多重集/序列类型的引用属性),我们使用 JS 数组来实现。