MEAN栈UML图绘制疑问:JavaScript原型对象与Angular设计模式的UML表示
Great question—this is a super common pain point when translating prototype-based JavaScript into class-centric UML, especially when you throw Angular's opinionated, pattern-heavy features into the mix. Let's break this down into two clear parts to make it manageable.
Since JavaScript uses prototype-based inheritance instead of class-based, you can't directly map it to standard UML class diagrams—but you can adapt UML with stereotypes and custom relationships to make the structure clear. Here are the most common approaches:
Use Class Diagrams with Stereotypes
Treat JS constructor functions as UML classes labeled<<constructor>>, and their associated prototype objects as separate classes labeled<<prototype>>. For example:- Create a class
Usermarked<<constructor>>with attributes likename(set in the constructor). - Create a class
UserPrototypemarked<<prototype>>with methods likesayHello(). - Add a dependency arrow (dashed line) from
UsertoUserPrototypelabeledprototypeto show the constructor's link to its prototype. - For instances (like
user1), show a generalization arrow (hollow triangle) from the instance toUserPrototypeto represent prototype inheritance—this makes the "instance inherits from prototype" relationship explicit.
- Create a class
Leverage Object Diagrams for Prototype Chains
If you need to visualize specific prototype chains (e.g.,user1 → User.prototype → Object.prototype), use a UML object diagram. Each object is a rectangle with its properties, and you add arrows labeled[[Prototype]]to show the chain between objects. This is great for explaining how inheritance works at the instance level.Custom Stereotyped Associations
Some teams prefer using a custom association labeled<<prototype-inheritance>>instead of generalization, since JS inheritance is between objects, not classes. This avoids confusion with traditional class-based generalization and makes the prototype relationship unambiguous.
Angular's core features are built around established design patterns—you can map these directly to UML using standard pattern notations plus Angular-specific stereotypes:
Dependency Injection (DI)
Angular's DI system is all about managing dependencies between components. Here's how to model it:
- Use dependency relationships (dashed arrows) in class diagrams to show which components depend on injectables. For example,
UserControllerwould have dashed arrows pointing to$scopeandUserService. - Label injectable services (like
UserService) with<<injectable>>to mark them as managed by Angular's DI container. - For the
$injectannotation, add a static attribute to the controller class like$inject: Array<string>and list the dependency names (e.g.,['$scope', 'UserService']) in the class's details. - To show the injection flow, use a sequence diagram: Start with the DI container resolving dependencies, then creating the controller instance, and injecting the required services/scope.
Factories & Providers
Angular factories and providers implement the Factory Method pattern. Model them like this:
- Mark factory classes with
<<factory>>and give them a method likecreateUser()that returns instances of your model (e.g.,User). Add a dependency arrow from the factory to the model class it produces. - Providers (which configure factories/services) get the
<<provider>>stereotype. Show a dependency from the provider to the corresponding factory or service, since providers are responsible for creating and configuring the injectable instance.
$scope & Scope Hierarchies
$scope is Angular's way of managing data and context between components:
- Create a base
Scopeclass labeled<<angular-scope>>with properties (e.g.,user,items) and methods (e.g.,$watch(),$apply()). - For parent-child scope relationships (like a controller scope nested inside a directive scope), use an aggregation relationship (hollow diamond) from the parent scope to the child scope, labeled
<<scope-hierarchy>>. Alternatively, use generalization if child scopes inherit behavior from parent scopes.
Routing
Angular's routing uses the State pattern to map URLs to components. Model it as:
- Create a
RouteConfigclass labeled<<route-config>>with attributes representing route rules (e.g.,path: '/users',controller: UserController,template: 'users.html'). - Add dependency arrows from
RouteConfigto the corresponding controller and template (label templates with<<view>>). - Use a sequence diagram to show the routing flow: When the URL changes,
$routeProvidermatches the route, resolves dependencies, instantiates the controller, injects$scope, and renders the view.
Singleton Services
Since Angular services are singletons by default, label service classes with <<singleton>> to make this behavior explicit. You can also add a note to the class explaining that the DI container manages a single instance.
Hope this gives you a concrete, actionable way to model both JS's prototype system and Angular's unique features in UML. The key is to keep it flexible—adapt these conventions to fit your team's needs and the level of detail you need to communicate.
内容的提问来源于stack exchange,提问作者Rach

