当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    深入理解Javascript里的依赖注入

    栏目:win服务器问题汇总 时间:2019-11-23 18:54


    迟早你需要用到其他开发人员的抽象成果——即你依靠别人的代码。我喜欢依赖自由(无依赖)的模块,但那是难以实现的。甚至你创建的那些漂亮的黑盒子组件也或多或少会依赖一些东西。这正是依赖注入大显身手的之处。现在有效地管理依赖的能力是绝对必要的。本文总结了我对问题探索和一些的解决方案。

    一、目标
    设想我们有两个模块。第一个是负责Ajax请求服务(service),第二个是路由(router)。
    复制代码 代码如下:
    var service = function() {
        return { name: 'Service' };
    }
    var router = function() {
        return { name: 'Router' };
    }
    我们有另一个函数需要用到这两个模块。
    复制代码 代码如下:
    var doSomething = function(other) {
        var s = service();
        var r = router();
    };
    为使看起来更有趣,这函数接受一个参数。当然,我们完全可以使用上面的代码,但这显然不够灵活。如果我们想使用ServiceXML或ServiceJSON呢,或者如果我们需要一些测试模块呢。我们不能仅靠编辑函数体来解决问题。首先,我们可以通过函数的参数来解决依赖性。即:
    复制代码 代码如下:
    var doSomething = function(service, router, other) {
        var s = service();
        var r = router();
    };
    我们通过传递额外的参数来实现我们想要的功能,然而,这会带来新的问题。想象如果我们的doSomething 方法散落在我们的代码中。如果我们需要更改依赖条件,我们不可能更改所有调用函数的文件。

    我们需要一个能帮我们搞定这些的工具。这就是依赖注入尝试解决的问题。让我们写下一些我们的依赖注入解决办法应该达到的目标:

    我们应该能够注册依赖关系
    1.注入应该接受一个函数,并返回一个我们需要的函数
    2.我们不能写太多东西——我们需要精简漂亮的语法
    3.注入应该保持被传递函数的作用域
    4.被传递的函数应该能够接受自定义参数,而不仅仅是依赖描述
    5.堪称完美的清单,下面 让我们实现它。
    三、RequireJS / AMD的方法
    你可能对RequireJS早有耳闻,它是解决依赖注入不错的选择。
    复制代码 代码如下:
    define(['service', 'router'], function(service, router) {      
        // ...
    });
    这种想法是先描述需要的依赖,然后再写你的函数。这里参数的顺序很重要。如上所说,让我们写一个叫做injector的模块,能接受相同的语法。
    复制代码 代码如下:
    var doSomething = injector.resolve(['service', 'router'], function(service, router, other) {
        expect(service().name).to.be('Service');
        expect(router().name).to.be('Router');
        expect(other).to.be('Other');
    });
    doSomething("Other");
    再继续之前我应该解释清楚doSomething函数体内容,我使用expect.js (断言方面的库)仅是为了保证我写的代码的行为和我期望的是一样的,体现一点点TDD(测试驱动开发)方法。
    下面开始我们的injector模块,这是非常棒的一个单例模式,所以它能在我们程序的不同部分工作的很好。
    复制代码 代码如下:
    var injector = {
        dependencies: {},
        register: function(key, value) {
            this.dependencies[key] = value;
        },
        resolve: function(deps, func, scope) {