Javascript 依赖项注入vs.托管依赖项vs.全局对象

Javascript 依赖项注入vs.托管依赖项vs.全局对象,javascript,oop,model-view-controller,backbone.js,requirejs,Javascript,Oop,Model View Controller,Backbone.js,Requirejs,我在一个Javascript+BackboneJS(MVC框架)+RequireJS框架中工作,但这个问题有点OO通用性 首先让我解释一下,在主干网中,视图是传统视图和控制器的混合体,HTML模板是传统的MVC视图 我为此绞尽脑汁已经有一段时间了,我不确定正确/务实的方法应该是什么 我有一个用户对象,它包含许多代码所依赖的用户首选项(如单位系统、语言选择等) 我的一些视图在不使用模板的情况下完成了大部分工作(通过使用第三方LIB,如映射和绘图LIB),因此它们依赖于用户对象来处理单位转换,例如。

我在一个Javascript+BackboneJS(MVC框架)+RequireJS框架中工作,但这个问题有点OO通用性

首先让我解释一下,在主干网中,视图是传统视图和控制器的混合体,HTML模板是传统的MVC视图

我为此绞尽脑汁已经有一段时间了,我不确定正确/务实的方法应该是什么

我有一个用户对象,它包含许多代码所依赖的用户首选项(如单位系统、语言选择等)

我的一些视图在不使用模板的情况下完成了大部分工作(通过使用第三方LIB,如映射和绘图LIB),因此它们依赖于用户对象来处理单位转换,例如。我目前正在使用RequireJS来管理这种依赖关系,而不会过多地破坏封装

我的一些视图本身所做的工作很少,只将模型数据传递给模板引擎/模板,模板引擎/模板完成了这些工作,并且确实依赖于用户对象,例如单位转换。将此依赖项传递到模板中的唯一方法是将其注入到模型中,然后将模型传递到模板引擎中

我的问题是,如何最好地处理如此广泛需要的依赖关系? -创建可在任何地方访问的应用程序范围的引用/全局对象?(YUK) -使用RequireJS托管依赖项,尽管通常只建议对类/对象定义而不是具体对象使用托管依赖项加载。
-或者,只使用依赖项注入,并手动将该依赖项传递到需要它的所有内容中?

我想你已经回答了自己的问题,你只是想让别人替你说:)使用DI,但你不是真正的“手动”将这种依赖性传递到所有内容中,因为您需要引用它来使用它。

从纯技术的角度来看,我认为可交换全局变量(可能发生变化的全局变量),特别是在javascript中,是危险和错误的。特别是因为javascript中充满了异步执行的部分代码。考虑下面的代码:

window.loggedinuser = Users.get("Paul");
addSomeStuffToLoggedinUser();
window.loggedinuser = Users.get("Sam");
doSomeOtherStuffToLoggedinUser();
现在,如果
addSomeStuffToLoggedinUser()
在某个地方异步执行(例如,它执行一个ajax调用,然后在第一个调用完成时执行另一个ajax调用),那么在第二个ajax调用之前,它很可能正在向新的loggedinuser(“Sam”)添加内容。显然不是你想要的

话虽如此,我甚至不太支持让一些用户对象从一个函数传递到另一个函数,无限期

就个人而言,要在这两种邪恶之间做出选择,我会选择一个“很少改变”的东西的全球范围——除非我在建造核电站或其他什么东西。因此,我倾向于让登录的用户在我的应用程序中全局可用,冒着这样的风险:如果出于某种原因,某些呼叫运行得很晚,并且我遇到一个用户注销,另一个用户直接登录的情况,则可能会发生奇怪的事情。(再说一次,如果一颗流星撞上我的应用程序所在的数据中心,也可能会发生一些奇怪的事情……我也不会对此采取防范措施)。实际上,一个可能的解决方案是在有人注销后重新加载整个应用程序

所以,我想这一切都取决于你的应用程序。有一件事让它变得更好(并且让你感觉你仍然得到了一些OO业力点),那就是将你的数据隐藏在一些命名的单例中:

var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser();
doSomethingCoolWith(myuser);
代替

doSomethingCoolWith(window.loggedinuser);

尽管最后几乎是一样的…

考虑到TDD方法,您将如何测试这一点?DI最适合于新项目,但JS在测试时为您提供了处理具体全局依赖关系的灵活选项,即:上下文构造。追溯到很久以前,Yahoo设计了一个模块模式,其中所有模块都是松散耦合的,互不依赖,但拥有全局上下文是可以的。这种全局上下文可以使你的应用程序构建对于不断重复使用的东西更加实用。只是你需要明智地/谨慎地应用它,而且需要有非常有力的证据证明这些东西是动态的。

对于它的价值,你可以找到一些很好的模式来缓解这个问题,方法是使用延迟来坐在可能被异步修改的可交换全局变量前面