我是JavaScript的新手。我想知道依赖注入是如何在JavaScript中实现的?我在网上搜索了一下,但什么也没找到。
发布于 2013-11-19 05:33:33
var Injector = {
dependencies: {},
add : function(qualifier, obj){
this.dependencies[qualifier] = obj;
},
get : function(func){
var obj = new func;
var dependencies = this.resolveDependencies(func);
func.apply(obj, dependencies);
return obj;
},
resolveDependencies : function(func) {
var args = this.getArguments(func);
var dependencies = [];
for ( var i = 0; i < args.length; i++) {
dependencies.push(this.dependencies[args[i]]);
}
return dependencies;
},
getArguments : function(func) {
//This regex is from require.js
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var args = func.toString().match(FN_ARGS)[1].split(',');
return args;
}
};
首先,我们需要一个配置来提供与限定符的必要依赖关系。为此,我们将依赖集定义为Injector类中的依赖项。我们使用依赖集作为容器,它将负责映射到限定符的对象实例。为了将带有限定符的新实例添加到依赖集,我们定义了一个add方法。然后,我们定义get方法来检索我们的实例。在此方法中,我们首先找到参数数组,然后将这些参数映射到依赖项。在此之后,我们只需使用依赖项构造对象并返回它。有关更多信息和示例,请参阅我博客上的post。
发布于 2014-02-10 05:24:15
您可以使用AngularJS作为示例。这是不是一件好事,你必须自己决定。我一周前写了一篇article about demistifying dependency injection in AngularJS。你可以在这里阅读文章中的代码:
// The following simplified code is partly taken from the AngularJS source code:
// https://github.com/angular/angular.js/blob/master/src/auto/injector.js#L63
function inject(fn, variablesToInject) {
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
if (typeof fn === 'function' && fn.length) {
var fnText = fn.toString(); // getting the source code of the function
fnText = fnText.replace(STRIP_COMMENTS, ''); // stripping comments like function(/*string*/ a) {}
var matches = fnText.match(FN_ARGS); // finding arguments
var argNames = matches[1].split(FN_ARG_SPLIT); // finding each argument name
var newArgs = [];
for (var i = 0, l = argNames.length; i < l; i++) {
var argName = argNames[i].trim();
if (!variablesToInject.hasOwnProperty(argName)) {
// the argument cannot be injected
throw new Error("Unknown argument: '" + argName + "'. This cannot be injected.");
}
newArgs.push(variablesToInject[argName]);
}
fn.apply(window, newArgs);
}
}
function sum(x, y) {
console.log(x + y);
}
inject(sum, {
x: 5,
y: 6
}); // should print 11
inject(sum, {
x: 13,
y: 45
}); // should print 58
inject(sum, {
x: 33,
z: 1 // we are missing 'y'
}); // should throw an error: Unknown argument: 'y'. This cannot be injected.
发布于 2016-12-23 02:40:29
我想说DI是JS/ES2015的一个开箱即用的特性。:-)当然,它不是功能齐全的IOC容器,但看起来很有用,不是吗?看看下面的例子!
const one = () => 1;
const two = ({one}) => one + one;
const three = ({one, two}) => one + two;
// IOC container
const decimalNumbers = {
get one() { return one(this); },
get two() { return two(this); },
get three() { return three(this); }
};
const binaryTwo = ({one}) => one + 9;
// child IOC container
const binaryNumbers = Object.create(decimalNumbers, {
two: { get() { return binaryTwo(this); } }
});
console.log(`${decimalNumbers.three} is ${binaryNumbers.three} in binary`);
您可以将依赖项包装在_.once
(请参阅underscore或lodash)中,以将它们转换为单例。
const rand = function() {
return (min, max) => min + Math.random() * (max - min) | 0;
};
const pair = function({rand} = this) {
return [rand(10, 100), rand(100, 1000)];
};
// IOC container
const ioc = Object.create({}, {
rand: {get: rand},
pair: {get: _.once(pair)} // singleton
});
console.log(`${[ioc.pair, ioc.pair === ioc.pair]}`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
https://stackoverflow.com/questions/20058391
复制相似问题