现在我们来接触一下AngularJS的DI($injector)。先从注入参数的解析开始:
function assertArgFn(arg, name, acceptArrayAnnotation) {
if (acceptArrayAnnotation && isArray(arg)) {
arg = arg[arg.length - 1];
}
assertArg(isFunction(arg), name, 'not a function, got ' +
(arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
//用来判定是否指function,不是的话,抛出相应的异常。
return arg;
}
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;//用来去除 function(a,b/*注释*/,c){} 中参数注释
var $injectorMinErr = minErr('$injector');
function annotate(fn) {
var $inject,
fnText,
argDecl,
last;
if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
if (fn.length) {
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
}
fn.$inject = $inject;//将要注入的部件名称数组,绑定到fn函数中。
}
} else if (isArray(fn)) {//判定fn是否为数组->判定数组fn最后一个是不是function->将fn数组前面的参数赋值给$inject
last = fn.length - 1;
assertArgFn(fn[last], 'fn');
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);//这个地方的代码有些绕圈,作用仅为抛出相应异常。o(╯□╰)o。true 参数是用来提高性能,减少fn是否为Array的判定。
}
return $inject;
}
以上代码主要是用来获取需要注入的参数。下面是例子
var a =[$a,$b,$c,function fn(...){...}];//$a,$b,$c为要注入到fn函数的具体引用。
annotate(a) //=>[$a,$b,$c];
var b =function(a,b/*我是注释*/,c);
annotate(b) //=>[a,b,c] 注意,这里a、b、c为字符串而不是引用。