现在开始看module
的初始化。
function setupModuleLoader(window) {//初始化angular以及和angular捆绑的第一个module
var $injectorMinErr = minErr('$injector');
var ngMinErr = minErr('ng');
function ensure(obj, name, factory) {
return obj[name] || (obj[name] = factory());
}
var angular = ensure(window, 'angular', Object);//每一个window下面只有一个angular实例的原因
// We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
//ensure(angular,'$$minErr',minErr);
angular.$$minErr = angular.$$minErr || minErr;
return ensure(angular, 'module', function() {//向angular写入module初始化函数
/** @type {Object.<string, angular.Module>} */
var modules = {};//记录一loadModules个angularjs下面所有的modules
return function module(name, requires, configFn) {
var assertNotHasOwnProperty = function(name, context) {
if (name === 'hasOwnProperty') {
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
}
};
assertNotHasOwnProperty(name, 'module');
if (requires && modules.hasOwnProperty(name)) {
modules[name] = null;//同名时,覆盖掉老的。感觉这个地方应该报错,而不是覆盖
}
return ensure(modules, name, function() {
if (!requires) {
throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
"the module name or forgot to load it. If registering a module ensure that you " +
"specify the dependencies as the second argument.", name);
}
/** @type {!Array.<Array.<*>>} */
var invokeQueue = [];
/** @type {!Array.<Function>} */
var runBlocks = [];
var config = invokeLater('$injector', 'invoke');//instanceCache.$injector =
/** @type {angular.Module} */
var moduleInstance = {
// Private state
_invokeQueue: invokeQueue,//用来记录注入到本module实例下面的各种具体方法函数。
_runBlocks: runBlocks,
requires: requires,
name: name,
provider: invokeLater('$provide', 'provider'),//$provide来自于上一节讲的providerCache
factory: invokeLater('$provide', 'factory'),
service: invokeLater('$provide', 'service'),
value: invokeLater('$provide', 'value'),
constant: invokeLater('$provide', 'constant', 'unshift'),
animation: invokeLater('$animateProvider', 'register'),
filter: invokeLater('$filterProvider', 'register'),
controller: invokeLater('$controllerProvider', 'register'),//这些provider以后挑着讲解
directive: invokeLater('$compileProvider', 'directive'),
config: config,
run: function(block) {
runBlocks.push(block);
return this;
}
};
if (configFn) {
config(configFn);//这也是为什么moduleconfig为function,按代码逻辑来讲它是支持注入的,但由于加载顺序,只能注入requires module里的attr
}
return moduleInstance;
/**
* @param {string} provider
* @param {string} method
* @param {String=} insertMethod
* @returns {angular.Module}
* 延迟加载
*/
function invokeLater(provider, method, insertMethod) {
return function() {
invokeQueue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};
}
});
};
});
总结一下,就是返回module创建函数,这个函数会创建module实例以及注入controller、directive、factory等。
var angularModule = setupModuleLoader(window);
try {
angularModule('ngLocale');
} catch (e) {
angularModule('ngLocale', []).provider('$locale', $LocaleProvider);//$LocaleProvider记录默认日期分隔符等信息
//这个地方,感觉不必要try catch ,直接angularModule('ngLocale', []).provider('$locale', $LocaleProvider);。前提是 module(name)name多次相同时,报错。
}
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
// $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
$provide.provider({
$$sanitizeUri: $$SanitizeUriProvider//格式化Uri
});
//$CompileProvider的源码1500行+。这里不讲
$provide.provider('$compile', $CompileProvider).
directive({
a: htmlAnchorDirective,
...//各种内置directive的注入。以后挑着讲
});
...//依旧是directive 的注入
$provide.provider({
$anchorScroll: $AnchorScrollProvider,
...//provider的注入,以后挑着讲
});
}
]);
}
为module注入内置的函数。并命名为ng
module。