Description
modules
module构成了我们的web应用。
从面向对象的角度来看,我们期望module拥有:
- 包含自身信息的属性,如name,requires(依赖)以及others;
- 供外界用于向module内部填充内容的方法,如constant,service,factory,directive以及controller等。
1. module对象
// 实现module类
function Module(name,requires) {
this.name = name;
this.requires = requires;
}
Module.prototype.constant = function (value) {
// 使该module拥有该value;
};
Module.prototype.service = function () {
// 使该module拥有该service
};
// 创建一个user module;
var userModule = new Module('user', null);
2. module对象的管理
为了方便对模块的管理,我们还需要一个变量来存储模块,一个简便的方法来新建或获取模块如:
var myAngular = {};
var modules = {};
// 新建或者获取模块,取决于是否传入requires参数
myAngular.module = function (name, requires) {
if (requires) {
return modules[name] = new Module(name, requires);
} else {
return modules[name];
}
};
angular内部对模块机制的实现大体是这个思路,只不过没有采用构造函数与原型的写法来新建模块,直接使用了对象的字面量写法。
var moduleInstance = {
name: name,// 模块名称
requires: requires,//模块依赖
constant: invokeLater('constant', 'unshift'),
provider: invokeLater('provider'),
_invokeQueue: invokeQueue
};
modules[name] = moduleInstance;
dependency injection
当使用依赖注入机制时,我们的期望是:当我们在特定的上下文中,需要使用别的值或者对象,甚至是类时,我们只需给出它们名称,然后就可以在接下来的上下文中直接使用它们。
1. 我们的期望
在angular中,我们很熟悉这样的代码:
function myController($scope, $window, myService) {
// 直接使用$scope,$window, myService。
}
我们希望的是直接在该函数内部使用$scope之类的对象。
2. 如何实现
在如何实现我们的期望之前,我们首先来看看我们最熟悉的函数 function。
在JavaScript中,function拥有作用域,从function的使用中我们就可以理解依赖注入的概念。
var a = 1;
var b = [1,2,3];
var c = {x: 1, y: 2};
function useThem(a, b, c) {
c.z = b.push(a);
}
useThem(a, b, c);
上面本身就是JavaScript中function的写法,使用参数可以直接从外部作用域去获取需要的值。
如我们之前提到的,函数的参数传递本身就符合我们的希望——使用名称,也可以说是标志来获取对应的值。
唯一不同的是,函数的参数代表什么是由函数调用时我们向它内部传递什么决定的,而我们在controller中的期望是当我声明好对应的参数时,这个参数所代表的值已经确定了,也就是函数声明时的参数决定了它的调用中传入什么参数。
要实现我们的期望,我们只需要增加一层逻辑,具体来说,也就是说我们需要统一我们函数的调用入口;
// 我们的函数
function myController($scope, $window, myService) {
// 直接使用$scope,$window, myService。
}
// 函数的统一调用入口
function invoke(fn, self) {
var argues = getArgs(fn);
fn.apply(self,argues);
}
// 获取函数依赖的方法。
// 1. 从哪里去获取依赖的标志, 从数组式的写法,还是$inject的写法,还是使用正则匹配来进行字符串匹配
// 2. 获取到依赖的标志后,按照该标志从哪里去取对应的值。
function getArgs(fn) {
// return what you want
}
也许,你已经想到需要一个cache变量来存储你所声明的可以被依赖注入的值了。
接下来,只要我们在调用我们的函数时使用统一的调用入口 invoke 方法时,便可以在函数内部自动根据参数的名称或者其他声明(数组式的依赖以及$inject式的声明依赖)来自动注入我们需要的值了。
由于我们在angular的框架中编码时,其实都是进行module内容的配置,真正帮我们去调用这些内容的是angular,它在内部实现了如上所述的invoke,以及getArgs逻辑。
当然,angular的依赖注入更为全面和复杂,不过,一切都是从这简单的逻辑开始的。
Activity