javascript中的依赖注入

时间:2013-03-03 19:21:46

标签: javascript performance unit-testing dependency-injection

我一直在玩javscript的依赖注入,但有一些我需要帮助的问题

一个简单的例子是我拥有的对话框模块,在页面上的多个位置使用,当用户与页面上的组件交互时,它会通过自定义消息向用户发出警告

function Dialog () {

}

Dialog.prototype.show = function () {

}

这可以在一个组件中使用,例如一个验证用户搜索的搜索控件,如果它是空的,它会触发一个错误对话框。依赖注入,我假设我会写:

function searchComponent (dialog) {
   this.dialog = dialog
}

searchComponent.prototype.validateSearch = function () {
    // validate search if invalid create error
    this.dialog.show();
}

var searchDialog = new Dialog();
var search = new searchComponent(searchDialog);

然而,用户可能永远不需要搜索错误对话框,但我正在创建它的实例,以便我可以传递依赖关系,如果我在页面上有100个单独的对话框实例,我会构建这些100次,这是不必要的,而且性能昂贵。

我宁愿做的是将对话框的构造延迟加载到需要的时间

searchComponent.prototype.validateSearch = function () {
  //validate search if invalid create error
  var dialog = new Dialog();
  dialog.show();
}

现在我知道这会产生不利之处,其中一个就是它对单元测试的影响,我很想知道的是我是否遗漏了某些东西或者替代方法?

提前致谢

4 个答案:

答案 0 :(得分:7)

JavaScript函数是第一类对象。不是传入构造的对话框,而是传入对话框构造函数:

var search = new SearchComponent(Dialog);

然后在需要时重启:

function SearchComponent(Dialog) {
  this.Dialog = Dialog;
}

SearchComponent.prototype.validateSearch = function() {
  var dialog = new this.Dialog();
  dialog.show();
}

答案 1 :(得分:1)

要扩展@ChrisTavares的优秀解决方案,您可以使用类似的内容在Dialog内部进行依赖注入:

var foo = function () { return new Foo() }; // just an example
var search = new SearchComponent(function() {
    return new Dialog(foo());
});

SearchComponent内:

function SearchComponent(Dialog) {
    this.Dialog = Dialog;
}

SearchComponent.prototype.validateSearch = function () {
    var dialog = new this.Dialog();
    dialog.show();
};

答案 2 :(得分:1)

受前面示例的启发,我创建了一个简单的jsFiddle,它利用一个名为Syringe.js的小型库,以显示如何通过预绑定SearchComponent来注入依赖项构造

创建SearchComponent对象时,会自动配置validator依赖项(一个单独的组件,此处取代实际对话框)。随后validateSearch方法使用此依赖关系。

以这种方式执行此操作的优点是,在创建每个SearchComponent对象实例时,您不必拥有任何依赖项。

此外,可以在创建validator对象后修改SearchComponent依赖项,并且可以相应地更新从属控件的行为。

答案 3 :(得分:0)

我最近编写了一个名为infect.js的依赖注入库。看看,可能就是你想要的。 https://github.com/amwmedia/infect.js