Javascript 为什么Angular JS中的依赖项注入比手工管理依赖项更好?

Javascript 为什么Angular JS中的依赖项注入比手工管理依赖项更好?,javascript,angularjs,dependency-injection,Javascript,Angularjs,Dependency Injection,具体说到DI特性,我不是Angular的粉丝,我也不太相信Angular使代码更易于测试,甚至使编写更多可测试代码更容易 在我看来,最终会有很多额外的抽象层,实际上是间接的,只是为了支持一些“魔法”——即使函数参数名自动实例化。如果没有这一特性——即:在调用函数时神奇地获得$http或$car的实例,或者其他任何东西——它似乎没有提供那么多 在使这些调用显式化的过程中,它需要付出多少额外的努力,间接性和魔力要少多少?最终得到的是一个“全局”(从应用程序的角度)命名空间。。。因此,不用手来做这些事

具体说到DI特性,我不是Angular的粉丝,我也不太相信Angular使代码更易于测试,甚至使编写更多可测试代码更容易

在我看来,最终会有很多额外的抽象层,实际上是间接的,只是为了支持一些“魔法”——即使函数参数名自动实例化。如果没有这一特性——即:在调用函数时神奇地获得$http或$car的实例,或者其他任何东西——它似乎没有提供那么多

在使这些调用显式化的过程中,它需要付出多少额外的努力,间接性和魔力要少多少?最终得到的是一个“全局”(从应用程序的角度)命名空间。。。因此,不用手来做这些事情真的只有一点方便

从文档中:

myModule.factory('greeter', function($window) {
  return {
    greet: function(text) {
      $window.alert(text);
    }
  };
});
function MyController($scope, greeter) {
  $scope.sayHello = function() {
    greeter.greet('Hello World');
  };
}
这里的神奇之处在于“greeter”是根据参数的名称自动注入的,对吗?我假设$scope也是一样的,尽管据我所知,所有控制器都应该将$scope作为第一个参数,所以情况可能并非如此

一个非魔法的例子:

function MyController() {
  var scope = myApp.get('scope');
  var greeter = myApp.get('greeter');
  scope.sayHello = function() {
    greeter.greet('Hello World');
  }
}
如您所见,我只是添加了一个“.get()”方法来获取依赖项。我知道这在Angular中是完全可能的,但这并不是我读过的文档所建议的主要情况

非魔法测试:

function myControllerTest() {
  var scope = {};
  var greeter = { greet: function() {} };
  myApp.set('scope', scope);
  myApp.set('greeter', greeter);
  // ... run an actual test on MyController here
}
我真的没有对Angular做过任何有意义的事情,但随着我年龄的增长和脾气的暴躁,我发现我越来越不喜欢魔法了。我非常乐意添加(比方说)20%以上的代码行,以避免间接层次,这意味着无论是框架还是语言,我都无法轻松地逐步完成我的代码


有人能给出一个合理的例子来说明angular在DI中做了些什么,而在一些基本约定下,它并不是相对容易解决问题的?仅仅为了避免显式定义依赖项,我就错过了“魔术”的好处吗?

依赖项注入是一种新奇的方式,在经典OOP文献中被称为“隔离”。这意味着对象不应该了解外部世界。这是封装的补充原则,即外部世界不应该知道对象的内部工作。实际上,这意味着如果使用依赖项注入,就不会使用全局变量。依赖注入不是一个框架,而是一个设计原则。Angulars DI框架只是为了让它更简单。正如您正确指出的,使用DI通常会引入间接寻址。这就是你付出的代价。如果你不同意,那很好。在许多情况下,DI无疑会使您的代码更难理解。不过,它带来了更具组合性和模块化的软件


在您的“非魔法”版本中,您基本上引入了“服务定位器”。这导致依赖于
myApp
。从DI的角度来看,这种依赖是最糟糕的,因为它是隐藏的、间接的和全局的“隐藏”表示它不是函数参数。只有阅读代码本身,才能看到它。间接的意思是,你真正关心的是迎宾员,而你依赖的是myApp。全球化应该是显而易见的。关于全局变量通常不好的原因有很多争论,但对于测试来说,问题是您的测试彼此共享状态。您不能以这种方式单独运行测试。这可能导致“测试片状”,这意味着某些测试有时失败,有时不失败,这取决于另一个测试。

首先,我完全理解你的观点

今天,我发现自己在使用任何js框架时都非常挑剔。它们似乎不知从何而来,其中很多,你最好多穿20%的衣服,避免那些多余的衣服

因为我对这一切都比较陌生,所以我不会在这里和你争论。。。让我也谈谈我对这个问题的看法

对于新手来说,掌握javascript这样的技术可能是一个相当大的挑战,我认为如果没有人在这一过程中透露一些信息,那么很容易从错误的角度出发。 特别是当您的目标是在应用程序中实现某种程度的复杂性时

我们都知道,好的图案提供了一个坚实的基础,这正是我第一次看到Angular时吸引我注意的地方

一切都在那里。简单、苗条、快速,易于开始和理解。背后的概念和模式是众所周知的,对我来说很有意义(DI、MVC、TDD、模块化、良好的关注点分离、强大的绑定策略),尽管当时我不知道如何用javascript实现它们

所以基本上它让我开始,让我开始得很好。今天,我知道的比以前多了一点,我看到很多其他框架都因为您指出的相同原因说再见。但是Angular留下来了,最初的架构也是如此,对我来说,那是巨大的

也许如果我有时间,我会自己找一个角度,只是为了踢它。。。但是当我想到它的时候,我想我不会让它有太大的不同。 那为什么要麻烦呢

此外,社区发展迅速,文档非常好,每个角落都有帮助

我知道你在这里谈论的是DI和可测试性,但这只是你从Angular得到的一小部分。仅出于这一目的,我相信你会很好地接受你的选择:)

顺便说一句,说到可测试性,看看angular scenario runner,我知道它正在停止(天知道为什么?!?),但是


这是一种魔力

myApp.get('scope')
-可能是哪个作用域^^@我想如果有人试图理解这首曲子