b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

JavaScript中的依赖注入

电脑杂谈  发布时间:2020-04-03 17:09:36  来源:网络整理

jscript 注入_jscript 注入_jscript.dll 调用失败

我喜欢编程正在管理复杂性的一句话. 也许您听说过计算机世界是一个巨大的抽象结构. 我们只是打包东西,并一遍又一遍地生产新工具. 考虑一下. 您使用的语言具有内置功能,这些功能可能是其他低级操作的抽象功能. 一样.

迟早您需要使用其他开发人员编写的抽象. 也就是说,您依赖别人的代码. 我喜欢模块没有依赖性,但这很难实现. 即使您创建了一些不错的黑匣子(如组件),您仍然可以将所有内容组合在一起. 这就是依赖注入发生的地方. 如今,有效管理依赖关系的能力绝对必要. 本文总结了我对此问题的看法.

假设我们有两个模块. 第一个是发出Ajax请求的服务,第二个是路由器.

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. 如果我们需要第三种依赖关系,会发生什么. 我们无法修改所有函数调用. 因此,我们需要一种工具来帮助我们做到这一点. 这就是依赖注入程序试图解决的问题. 让我们写下我们要实现的一些目标:

一个不错的清单,不是吗?让我们找出答案.

jscript 注入_jscript 注入_jscript.dll 调用失败

requirejs / AMD方法

您可能已经知道requirejs. 这是解决依赖关系的好方法.

define(['service', 'router'], function(service, router) {       
    // ...
});

这个想法是首先描述所需的依赖关系jscript 注入,然后编写函数. 参数的顺序在这里当然很重要. 假设我们将编写一个名为jector的模块,该模块将接受相同的语法.

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方法.

我们的喷油器模块从这里开始. 成为单例对象很棒,因此它可以在应用程序的不同部分完成其工作.

var injector = {
    dependencies: {},
    register: function(key, value) {
        this.dependencies[key] = value;
    },
    resolve: function(deps, func, scope) {
    }
}

一个非常简单的对象,具有两个功能和一个变量作为存储. 我们要做的就是检查deps数组,并在dependencies变量中搜索答案. 其余的只是为传递的func参数调用.apply方法.

resolve: function(deps, func, scope) {
    var args = [];
    for(var i=0; i < deps.length, d=deps[i]; i++) {
        if(this.dependencies[d]) {
            args.push(this.dependencies[d]);
        } else {
            throw new Error('Can\\'t resolve ' + d);
        }
    }
    return function() {
        func.apply(scope || {}, args.concat(Array.prototype.slice.call(arguments, 0)));
    }        
}

jscript.dll 调用失败_jscript 注入_jscript 注入

如果有任何范围,它将有效地工作. Array.prototype.slice.call(参数,0)是将参数变量转换为实际数组所必需的. 这种实现方式的问题在于,我们必须将所需的组件编写两次,并且不能真正混合它们的顺序. 其他自定义参数始终遵循相关性.

根据Wikipedia,反射是程序在运行时检查和修改对象的结构和行为的能力. 简而言之,在JavaScript的上下文中,它是读取对象或函数的源代码并对其进行分析. 让我们从一开始就获得doSomething函数. 如果输出doSomething.toString(),则会得到以下字符串:

"function (service, router, other) {
    var s = service();
    var r = router();
}"

将此方法用作字符串可以使我们获得所需的参数. 而且,更重要的是他们的名字. 这是Angular用于实现依赖注入的方法. 我做了一个小小的改动,得到了一个正则表达式,它直接从Angular的代码中派生参数.

/^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m

我们可以将resolve类更改为以下内容:

resolve: function() {
    var func, deps, scope, args = [], self = this;
    func = arguments[0];
    deps = func.toString().match(/^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m)[1].replace(/ /g, '').split(',');
    scope = arguments[1] || {};
    return function() {
        var a = Array.prototype.slice.call(arguments, 0);
        for(var i=0; i < deps.length; i++) {
            var d = deps[i];
            args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());
        }
        func.apply(scope || {}, args);
    }        
}

我们根据函数的定义运行RegExp. 结果是:

["function (service, router, other)", "service, router, other"]

所以我们只需要第二项. 清除空白空间并分割字符串后,我们填充了deps数组. 另一个更改:

jscript.dll 调用失败_jscript 注入_jscript 注入

var a = Array.prototype.slice.call(arguments, 0);
...
args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());

我们遍历依赖关系,如果缺少某些内容,我们将尝试从arguments对象获取它. 幸运的是,如果数组为空,则shift方法返回undefined. 他不会抛出错误. 新版本的注射器可以像这样使用:

var doSomething = injector.resolve(function(service, other, router) {
    expect(service().name).to.be('Service');
    expect(router().name).to.be('Router');
    expect(other).to.be('Other');
});
doSomething("Other");

无需重复编写依赖项,我们可以混合使用它们的顺序. 仍然有效,我们复制了Angular的魔力.

但是,世界并不完美,反射注入存在很大的问题. 压缩会破坏我们的逻辑. 那是因为它更改了参数的名称,而我们将无法解析依赖关系. 例如:

var doSomething=function(e,t,n){var r=e();var i=t()}

这是我们的doSomething函数传递给压缩器的地方. Angular团队提出的解决方案如下:

var doSomething = injector.resolve(['service', 'router', function(service, router) {
}]);

看起来就像我们开始时一样. 我个人找不到更好的解决方案,因此我决定将两种方法混合使用. 这是注射器的最终版本.

var injector = {
    dependencies: {},
    register: function(key, value) {
        this.dependencies[key] = value;
    },
    resolve: function() {
        var func, deps, scope, args = [], self = this;
        if(typeof arguments[0] === 'string') {
            func = arguments[1];
            deps = arguments[0].replace(/ /g, '').split(',');
            scope = arguments[2] || {};
        } else {
            func = arguments[0];
            deps = func.toString().match(/^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m)[1].replace(/ /g, '').split(',');
            scope = arguments[1] || {};
        }
        return function() {
            var a = Array.prototype.slice.call(arguments, 0);
            for(var i=0; i < deps.length; i++) {
                var d = deps[i];
                args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());
            }
            func.apply(scope || {}, args);
        }        
    }
}

jscript.dll 调用失败_jscript 注入_jscript 注入

resolve方法接受两个或三个参数. 如果是两个,就像我们最近写的. 是的,如果有三个参数,它将获取第一个参数jscript 注入,然后解析它并填充deps数组. 这是测试用例:

var doSomething = injector.resolve('router,,service', function(a, b, c) {
    expect(a().name).to.be('Router');
    expect(b).to.be('Other');
    expect(c().name).to.be('Service');
});
doSomething("Other");

您可能会注意到有两个逗号,一个接一个. 这不是一个错误. 空值实际上表示“其他”参数. 这就是我们控制参数顺序的方式.

有时我使用第三种注射方法. 它涉及对函数作用域(或换句话说,此对象)的操作. 因此,它并不总是合适的.

var injector = {
    dependencies: {},
    register: function(key, value) {
        this.dependencies[key] = value;
    },
    resolve: function(deps, func, scope) {
        var args = [];
        scope = scope || {};
        for(var i=0; i < deps.length, d=deps[i]; i++) {
            if(this.dependencies[d]) {
                scope[d] = this.dependencies[d];
            } else {
                throw new Error('Can\\'t resolve ' + d);
            }
        }
        return function() {
            func.apply(scope || {}, Array.prototype.slice.call(arguments, 0));
        }        
    }
}

我们要做的就是将依赖项附加到作用域. 这样做的好处是,开发人员不应将依赖项作为参数编写. 它们只是功能范围的一部分.

var doSomething = injector.resolve(['service', 'router'], function(other) {
    expect(this.service().name).to.be('Service');
    expect(this.router().name).to.be('Router');
    expect(other).to.be('Other');
});
doSomething("Other");

依赖注入是我们所有人要做的事情之一,但从未考虑过. 即使您没有听过这个词,您也可能已经使用了数百万次.

可以在这里看到本文提到的所有示例.

原始文本:


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-162665-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...