说明:
内容主要包括三部分:
1.按源码的结构顺序 对 全部的变量及方法的说明
2.requirejs运行流程
三、流程相关图片node
为了方便比对源码,按源码的结构顺序展现。数组
var requirejs, require, define; (function (global, setTimeout) { var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, version = '2.3.5', commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/mg, //去除注释 cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,//提取require函数的arguments jsSuffixRegExp = /\.js$/, currDirRegExp = /^\.\//, op = Object.prototype, ostring = op.toString, hasOwn = op.hasOwnProperty, isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), isWebWorker = !isBrowser && typeof importScripts !== 'undefined', readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? /^complete$/ : /^(complete|loaded)$/, defContextName = '_', isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', contexts = {}, cfg = {}, globalDefQueue = [], useInteractive = false; //返回singlePrefix或空 function commentReplace(match, singlePrefix) {} //判断函数 function isFunction(it) {} //判断数组 function isArray(it) {} //执行函数func(ary[i], i, ary);返回真值,跳出循环 function each(ary, func) {} //与each序列反 function eachReverse(ary, func) {} //判断obj是否有prop function hasProp(obj, prop) {} //返回obj上的prop function getOwn(obj, prop) {} //循环调用func(obj[prop], prop);返回真值,跳出循环 function eachProp(obj, func) {} //混合source属性值(target没有同名的)到target //force为真,target同名覆盖,deepStringMixin为真,深混合 function mixin(target, source, force, deepStringMixin) {} //返回逆名函数,执行为obj调用fn函数 function bind(obj, fn) {} //返回script元素的集合 function scripts() {} //throw err; function defaultOnError(err) {} //例getGlobal("aa.bb");为global.aa.bb function getGlobal(value) {} //生成一个错误 function makeError(id, msg, err, requireModules) {} if (typeof define !== 'undefined') { return; } if (typeof requirejs !== 'undefined') { if (isFunction(requirejs)) { return; } cfg = requirejs; requirejs = undefined; } if (typeof require !== 'undefined' && !isFunction(require)) { cfg = require; require = undefined; } function newContext(contextName) { var inCheckLoaded, Module, context, handlers, checkLoadedTimeoutId, config = { waitSeconds: 7, baseUrl: './', paths: {}, bundles: {}, pkgs: {}, shim: {}, config: {} }, registry = {}, enabledRegistry = {}, undefEvents = {}, defQueue = [], defined = {}, urlFetched = {}, bundlesMap = {}, requireCounter = 1, unnormalizedCounter = 1; //ary中.删除此项;..删此项和前一项除(i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1]==='..') function trimDots(ary) {} //路径处理.config.pkgs有name值优先,无值按相对路径转化,apply是否启用地图配置 function normalize(name, baseName, applyMap) {} //删除data-requiremoduley为name和data-requirecontext === context.contextName的script function removeScript(name) {} //先移除再加载模块; function hasPathFallback(id) {} //第一个"!"分离的先后数据 return [prefix, name]; function splitPrefix(name) {} //返回模块的属性对象 // return { // prefix: prefix, // name: normalizedName, // parentMap: parentModuleMap, // unnormalized: !!suffix, // url: url, // originalName: originalName, // isDefine: isDefine, // id: (prefix ? // prefix + '!' + normalizedName : // normalizedName) + suffix // }; function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {} //registry[id]有值取值,没值生成新的context.Module对象,并赋给registry[id] function getModule(depMap) {} //模块加载完且name为defined 或 加载出错且name为error ? 执行fn : 模块绑定事件 function on(depMap, name, fn) {} //errback ? 执行errback(err) : mod.emit('error', err)执行删除操做 function onError(err, errback) {} //将globalDefQueue推入defQueue function takeGlobalQueue() {} //commonjs风格 handlers = { //mod.require ? 返回mod.require : localRequire 'require': function (mod) {}, 'exports': function (mod) {}, 'module': function (mod) {} }; //清除registry[id]、enabledRegistry[id] function cleanRegistry(id) {} //递归mod.depMaps,执行mod.check(); function breakCycle(mod, traced, processed) {} //检查加载状态,不一样状态执行不一样操做 function checkLoaded() {} Module = function (map) { this.events = getOwn(undefEvents, map.id) || {}; this.map = map; this.shim = getOwn(config.shim, map.id); this.depExports = []; this.depMaps = []; this.depMatched = []; this.pluginMaps = {}; this.depCount = 0; }; Module.prototype = { //初始化,根据options.enabled ? this.enable() : this.check() init: function (depMaps, factory, errback, options) {}, //经过this.depCount判断依赖是否加载完成 defineDep: function (i, depExports) {}, // map.prefix ? this.callPlugin() : this.load(); fetch: function () {}, //经过context.load调req.load加载js文件 load: function () {}, //define模块调用 check: function () {}, //加载依赖 callPlugin: function () {}, //data-main上的模块调用,define模块调用 enable: function () {}, //将cb推入this.events[name] on: function (name, cb) {}, //name === 'error'删this.events[name];不然循环this.events[name]执行cb(evt); emit: function (name, evt) {} }; //module.init内执行check()非enable(); function callGetModule(args) {} //移除监听事件 function removeListener(node, func, name, ieName) {} //移除监听事件,返回节点 function getScriptData(evt) {} // 获取并加载defQueue中的模块 function intakeDefines() {} context = { config: config, contextName: contextName, registry: registry, defined: defined, urlFetched: urlFetched, defQueue: defQueue, defQueueMap: {}, Module: Module, makeModuleMap: makeModuleMap, nextTick: req.nextTick, onError: onError, //配置参数 调用context.require(cfg.deps || [], cfg.callback); configure: function (cfg) {}, //返回闭包接口供调用 makeShimExports: function (value) {}, //返回闭包接口供调用 makeRequire: function (relMap, options) { //makeRequire的实际执行函数,生成宏任务; function localRequire(deps, callback, errback) { return localRequire; } mixin(localRequire, { isBrowser: isBrowser, toUrl: function (moduleNamePlusExt) {}, defined: function (id) {}, specified: function (id) {} }); if (!relMap) { localRequire.undef = function (id) {}; } return localRequire; }, //调用 module的enable() enable: function (depMap) {}, //完成加载后 completeLoad: function (moduleName) {}, //根据moduleName获取url nameToUrl: function (moduleName, ext, skipExt) {}, //调用req.load() load: function (id, url) {}, //return callback.apply(exports, args); execCb: function (name, callback, args, exports) {}, //加载完成后 onScriptLoad: function (evt) {}, //加载错误 onScriptError: function (evt) {} }; context.require = context.makeRequire(); return context; } //入口函数 req = requirejs = function (deps, callback, errback, optional) {}; //return req(config); req.config = function (config) {}; //宏任务 req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { setTimeout(fn, 4); } : function (fn) { fn(); }; //req赋值给require if (!require) { require = req; } req.version = version; req.jsExtRegExp = /^\/|:|\?|\.js$/; req.isBrowser = isBrowser; s = req.s = { contexts: contexts, newContext: newContext }; //初始调用 req({}); each([ 'toUrl', 'undef', 'defined', 'specified' ], function (prop) { req[prop] = function () { var ctx = contexts[defContextName]; return ctx.require[prop].apply(ctx, arguments); }; }); if (isBrowser) { head = s.head = document.getElementsByTagName('head')[0]; baseElement = document.getElementsByTagName('base')[0]; if (baseElement) { head = s.head = baseElement.parentNode; } } req.onError = defaultOnError; //建立节点 req.createNode = function (config, moduleName, url) {}; //节点绑定事件,添加到头部,并返回节点 req.load = function (context, moduleName, url) {}; //返回状态为interactive的节点 function getInteractiveScript() {} //data-main上的值解析赋给cfg if (isBrowser && !cfg.skipDataMain) { eachReverse(scripts(), function (script) { if (!head) { head = script.parentNode; } dataMain = script.getAttribute('data-main'); if (dataMain) { mainScript = dataMain; if (!cfg.baseUrl && mainScript.indexOf('!') === -1) { src = mainScript.split('/'); mainScript = src.pop(); subPath = src.length ? src.join('/') + '/' : './'; cfg.baseUrl = subPath; } mainScript = mainScript.replace(jsSuffixRegExp, ''); if (req.jsExtRegExp.test(mainScript)) { mainScript = dataMain; } cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; return true; } }); } //定义模块的函数 define = function (name, deps, callback) {}; define.amd = { jQuery: true }; req.exec = function (text) {}; //将data-main的值解析代入req函数; req(cfg); }(this, (typeof setTimeout === 'undefined' ? undefined : setTimeout)));
一、初始化变量;
二、执行 req({})闭包
req({})
context = contexts[contextName] = req.s.newContext(contextName);
说明:contextName='_',返回context这个东西,context.require = context.makeRequire();=localRequire;调用makeRequire实际调用makeRequire里的localRequireapp
context.configure(cfg);
说明:cfg=config={},什么都没干函数
return context.require(deps, callback, errback);
说明:调用makeRequire里的localRequire;deps=[];requirejs
intakeDefines();
takeGlobalQueue();
说明:intakeDefines的子函数,二者什么都没执行fetch
context.nextTick(function () { intakeDefines(); requireMod = getModule(makeModuleMap(null, relMap)); requireMod.skipMap = options.skipMap; requireMod.init(deps, callback, errback, { enabled: true }); checkLoaded(); });
说明:产生一个 宏任务1 函数;req({})函数完ui
三、执行 req(cfg)
获取data-main上的值并解析成cfgthis
req(cfg);
说明:cfg={baseUrl:"data-main解析值1",deps:[data-main解析值2]}url
context = getOwn(contexts, contextName);
说明:获取以前产生的context;
context.configure(cfg);
说明:cfg=config={baseUrl:"data-main解析值1",deps:[data-main解析值2]}
config[prop] = value;
说明:属性值给config
context.require(cfg.deps || [], cfg.callback);
说明:调用makeRequire里的localRequire;deps=[data-main解析值2];
intakeDefines(); takeGlobalQueue();
说明:什么都没执行
context.nextTick(function () {
说明:产生一个 宏任务2 函数;
return context.require(deps, callback, errback);
说明:调用makeRequire里的localRequire;deps=[];
intakeDefines(); takeGlobalQueue();
说明:什么都没执行
context.nextTick(function () {
说明:产生一个 宏任务3 函数;req(cfg);函数完
四、第一个宏任务开始
intakeDefines(); takeGlobalQueue();
说明:什么都没执行
requireMod = getModule(makeModuleMap(null, relMap));
makeModuleMap(null, relMap)
说明:返回一个对象obj
nameParts = splitPrefix(name);
说明:name="_@r2"
normalizedName = normalize(name, parentName, applyMap); url = context.nameToUrl(normalizedName);
parentModule = syms.slice(0, i).join('/');
说明:parentModule="_@r2"
getModule(obj)
new context.Module(depMap)
说明:depMap=上面返回的对象obj;getModule返回context.Module实例requireMod
requireMod.init(deps, callback, errback, {enabled: true}); this.enable(); enabledRegistry[this.map.id] = this; this.check(); cleanRegistry(id);
this.emit('defined', this.exports); checkLoaded();
说明:什么都没执行,第一个宏任务完。
五、第二个宏任务开始
intakeDefines(); takeGlobalQueue();
说明:什么都没执行
requireMod = getModule(makeModuleMap(null, relMap));
makeModuleMap(null, relMap)
说明:返回一个对象obj
nameParts = splitPrefix(name);
说明:name="_@r3"
normalizedName = normalize(name, parentName, applyMap); url = context.nameToUrl(normalizedName);
parentModule = syms.slice(0, i).join('/');
说明:parentModule="_@r3"
getModule(obj)
new context.Module(depMap)
说明:depMap=上面返回的对象obj;getModule返回context.Module实例requireMod
requireMod.init(deps, callback, errback, {enabled: true});
说明: deps 变为 data-main解析值2
this.enable(); enabledRegistry[this.map.id] = this; depMap = makeModuleMap(depMap,(this.map.isDefine ? this.map : this.map.parentMap), false,!this.skipMap); nameParts = splitPrefix(name); normalizedName = normalize(name, parentName, applyMap); url = context.nameToUrl(normalizedName); " on(depMap, 'defined', bind(this, function (depExports) {this.defineDep(i, depExports);this.check();})); " mod = getModule(depMap); mod = registry[id] = new context.Module(depMap); mod.on(name, fn); getModule(depMap).enable(); this.check(); checkLoaded();
说明: 宏任务2结束
六、宏任务3同宏任务1
七、执行data-main引入的文件的require函数
require(['./example'],function(example){example.test();}); req = requirejs = function (deps, callback, errback, optional) { return context.require(deps, callback, errback); intakeDefines(); takeGlobalQueue(); context.nextTick(function () {
说明: 产生一个宏任务4函数;require函数结束
onScriptLoad: function (evt) { var data = getScriptData(evt); context.completeLoad(data.id); shim = getOwn(config.shim, moduleName) || {}, takeGlobalQueue(); callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
说明: require函数结束后执行
八、宏任务4同宏任务2
说明: deps变为 要加载的依赖