相信用过AngularJS框架的jser应该都知道依赖注入的概念。依赖注入(Dependency Injection)简称DI,做过后台的程序员应该都不会陌生,因为很多后端语言,诸如C#、JAVA都有很好的框架支持,如JAVA中的Spring和C#中的Autofac。
关于控制反转(IOC)、依赖注入(DI),博客园有一篇好文依赖注入那些事儿。
分析
依赖注入本质用途就是解决项目中的硬编码,降低代码耦合度,有效的管理模块依赖。RequireJS和AngularJS都有依赖注入的解决方案,AngularJS有一个内在的依赖注入机制,使用AngularJS,你可以把你的App分成许多个可以重复使用的组件,当需要这些组件的时候,可以通过依赖注入把这些组件注入到你的App中去。
RequireJS1
2
3define(['module1','module2'], function(module1, module2) {
// ...
});
AngularJS1
2
3
4
5
6angular.module('gulpAngular',
[
'ngAnimate',
'ngCookies',
'ngTouch'
]);
使用依赖注入我们应该要达到以下目标
1、我们应该能够注册依赖关系
2、注入应该接受一个函数,并返回一个我们需要的函数
3、我们不能写太多东西——我们需要精简漂亮的语法
4、注入应该保持被传递函数的作用域
5、被传递的函数应该能够接受自定义参数,而不仅仅是依赖描述
6、堪称完美的清单,下面 让我们实现它。
代码实现
首先,定义一个对象叫做injector,1
2
3
4
5
6
7
8
9
10var injector = {
dependencies: {},
register: function(name, src) {
this.dependencies[name] = src;
},
resolve: function(target) {
}
};
`
injector对象中有两个方法,regist负责注册需要依赖的模块并存在dependencies中,第二个方法是resolve,这个方法接收的参数是我们我们要注入依赖的对象,这里的关键的点就是这个注入器不应该调用我们的函数,所以我们在resolve方法中返回一个闭包来包裹我们的target,然后再调用它:1
2
3
4
5resolve: function(target) {
return function() {
target();
};
}
下一步到AngularJS源码中找到annotate方法,此方法将目标函数转换为一个字符串,删除它的注释(如果有),然后提取他的参数(依赖项):1
2
3
4
5
6
7
8
9
10
11
12
13var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
fnText = target.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS)[1].split(/, ?/g);
var args = [];
for (var i = 0; i < argDecl.length; i++) {
if (this.dependencies[argDecl[i]]) {
args.push(this.dependencies[argDecl[i]]);
}
}
return function () {
target.apply({}, args);
}
1 | var injector = { |