AngularJS中的模块和名称空间/名称冲突

考虑下面的jfiddle http://jsfiddle.net/bchapman26/9uUBU/29/

//angular.js example for factory vs service var app = angular.module('myApp', ['module1', 'module2']); var service1module = angular.module('module1', []); service1module.factory('myService', function() { return { sayHello: function(text) { return "Service1 says \"Hello " + text + "\""; }, sayGoodbye: function(text) { return "Service1 says \"Goodbye " + text + "\""; } }; }); var service2module = angular.module('module2', []); service2module.factory('myService', function() { return { sayHello: function(text) { return "Service2 says \"Hello " + text + "\""; }, sayGoodbye: function(text) { return "Service2 says \"Goodbye " + text + "\""; } }; }); function HelloCtrl($scope, myService) { $scope.fromService1 = myService.sayHello("World"); } function GoodbyeCtrl($scope, myService) { $scope.fromService2 = myService.sayGoodbye("World"); }​ 

我有2个模块(module1和module2)。 module1和module2都定义了一个名为myService的服务。 当两个模块都被导入到myApp中时,这似乎在Angular中的myService上创build名称冲突。 看来AngularJs只是使用第二个服务定义而不会提醒你可能的问题。

非常大的项目(或者只是重复使用模块)可能会冒名称冲突的风险,这可能很难debugging。

有没有办法给名称添加模块名称,以避免名称冲突?

到目前为止,AngularJS模块不提供任何types的命名空间,以防止不同模块中的对象之间发生冲突。 原因是AngularJS应用程序只有一个注入器,它为所有对象保存名称而不考虑模块名称。

AngularJS开发者指南说:

为了pipe理依赖创build的责任,每个Angular应用程序都有一个注入器。 注入器是一个服务定位器,负责构build和查找依赖关系。

正如你所提到的,注入模块到主/应用程序模块时可能会导致令人讨厌的错误。 当碰撞发生时,他们保持沉默,赢家由最后一个模块注入决定。

所以不,没有一个避免这些冲突的方法。 也许这将在未来发生。 对于这个问题变得更可能的大型应用程序来说,你是对的,命名约定是你最好的工具。 考虑属于模块或function区域的对象是否可能使用短前缀。

您可以通过使用约定来命名您的模块以避免这种情况,使它们始终是唯一的。

一种方法是看其他语言如何做。 例如,在Java中,类的“全名”基于文件的名称和文件夹。例如,如果在MyArtStuff文件夹中有一个名为Bitmap.java的Java文件,则类的全名将会是MyArtStuff.Bitmap

原来,AngularJS允许你将点(。)作为模块名称的一部分,所以你可以使用名字约定。

例如,如果开发人员在脚本“MainPage \ Module1.js”中创build一个名为“ModuleA”的模块,他们应该将模块命名为“MainPage.Module1.ModuleA”。 因为每个path和文件名在您的应用程序中是唯一的,所以您的模块名称将是唯一的

你只需让开发者遵循这个约定。

请注意,Rockallite指出,这将无助于在多个模块中具有相同名称的服务,控制器等。 但是,您可以使用类似的方法来生成这些元素,并在这些元素的名称前加上前缀。

理想情况下,AngularJS会有名称空间,将来可能会有。 在此之前,我们能做的最好的事情就是在命名空间被发明之前做开发者已经做了40多年的事情,并且尽我们所能为我们的元素加上前缀。

在你想要服务的模块上定义你的控制器。

service2Module.controller("ServiceTwoCtrl", function(myService, $scope) {});