JavaScript的UML?

12

我正在寻找一种图形化表示JavaScript对象的方法...

我知道有UML,但是例如,如何表示两个对象之间的关系,例如:

var a, b;

a = {};
b = Object.create(a);

直观来说,我会画出这样的东西:

+-----+
|b    |
|-----|
|     |
+--+--+
   |     +-----+
   +---->|a    |
         |-----|
         |     |
         +-----+

但是在UML中有一个好的表示方式吗?

那么 混入 呢?

c = $.extend({}, a, b)

+-----+           +-----+
|a    |           |b    |
|-----|           |-----|
|     |<----------|     |
+-----+           +-----+
   +     +-----+
   |     |c    |
   |     |-----|
   +---->|     |
         +-----+
3个回答

7

首先需要知道的是,JavaScript使用基于原型的继承。这意味着与其他面向对象语言(例如Java)不同,没有类和实例之间的区别,只有对象。其中一个影响是区分对象图是没有意义的。

针对您的第一个示例:

var a, b;

a = {};
b = Object.create(a);

这是继承 - 对象b继承了对象a的属性。
在UML中正确建模的方法是使用以下类/对象图:

object b inherits from object a

混入可以看作是多重继承的一种形式,对象c从对象ab继承属性,其图示可能如下所示:

object c inherits from a and b


1
并不完全准确地说,对象和它的类之间没有区别。至少从类型理论的角度来看是这样的。任何对象都有一个给定的类型。具有相同原型的任何对象都派生自相同的类型,并且具有相同原型和相同对象属性的任何对象都具有相同的类型。因此,您可以拥有并且确实可能拥有比类型更多的对象。然而,这并不否定您的观点 :) - Rune FS
更加技术上正确的说法是,在JavaScript中没有类的表示。 - Sled
由于这篇文章已经发表了几年,因此让我向其他阅读者明确一点:ECMAScript 2015 现在包括类,并且不会偏离基于原型的继承。[链接](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) - Nightforce2

3

看起来你正在尝试在类图中展示对象实例之间的关系。这不会真正起作用;你可能想尝试使用UML实例图(也称为对象图)。类图旨在以静态方式捕获系统概念、结构和它们之间的关系。从一个类图开始,然后移动到一个实例图可能有所帮助,在实例图中,你可以将一些值放入你对象实例的“插槽”或属性中,以查看你类图中的模型是否有效。


1

你的例子代表对象之间的关系,而不是类之间的关系,因此UML对象图是正确的选择(正如RobertMS已经指出的那样)。

这些对象之间的关系是指(在第一个案例中)对象a是对象b的原型。我会使用依赖关系来表示这种关系。维基百科对UML依赖符号有很好的描述here

使用依赖关系的理由是它反映了“对被影响或独立建模元素的更改可能会影响依赖建模元素的语义”的概念。由于我们经常使用原型对象来保存一组“依赖”对象(即同一“类”的对象)的默认属性和方法,因此使用依赖关系似乎是合理的,如果不是有点争议的话。

我会用“<<proto>>”来标记这个依赖关系的构造型。

虽然UML确实给你很大的灵活性,但遵循惯例是很好的。

Scott Ambler的这个页面上有关于对象图的很好的介绍。

在你的第二个例子中,使用jQuery的extend函数,你没有真正的原型关系,但是你正在将一些对象的属性合并到另一个对象中。在这种情况下,我不确定是否有一个特定的总体建模术语来描述这种情况。不过,这里有一种依赖关系。我建议查看标准UML依赖关系的列表(列在上述维基百科页面上),看看是否有任何东西适用于你的特定应用程序。也许<<refine>>适合你?


为什么不使用继承?我认为在这种情况下更适合使用继承,因为继承表明两个对象之间的关系比依赖关系更密切。我会忽略你不应该使用类图,因为UML并没有考虑基于原型的继承。 - romario333
如果OP的示例不同,例如具有原型和将其原型链接到Shape.prototype的Shape ctor和Circle ctor,则我会使用UML继承来处理JS!但是OP仅显示了单个对象,并且从未显示过任何看起来像子类化的东西。我所能看到的只是从其他对象派生出的对象。如果有什么区别,在第一个示例中,更像是“a”是“类型”,而“b”是“实例”(这就是如何使用Object.create)。没有子类化。不过,我确实同意您的观点,即我们应该利用UML的灵活性,并在必要时忽略某些事情。 - Ray Toal
仅使用Object.create进行继承是相当常见的做法。我认为继承在这里更好的原因之一是,对象a中的任何属性都会被b“继承”,它们成为了b的接口的一部分。 - romario333
你的方法是强调原型链。如果你想向某人解释原型链和属性查找的工作原理,这可能是可以的。但在我看来,这不是一个常见的情况。最终,这取决于你图表的目标受众 :-) - romario333
当然,这没问题。在JavaScript中,传统的UML继承链接没有任何问题,因为你可以使用原型模拟接口继承。无论是否常见,我读到OP的问题的方式(对我来说似乎非常清楚!)是问“我如何表示对象之间的特定关系?”也许问题的意图是其他什么,谁知道呢。显然,如果目标受众是消费高级模型,则类图就可以了。 - Ray Toal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接