如今開始看module
的初始化。html
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; }; } }); };
});angularjs
總結一下,就是返回module建立函數,這個函數會建立module實例以及注入controller、directive、factory等。bootstrap
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。ide