requirejs--源码分析

   1 /*---------------------------------------start-------------------------------*/
   2 req({}); // num == 1 跳到 num == 2
   3
   4 //Exports some context-sensitive methods on global require.
   5 each([
   6     ‘toUrl‘,
   7     ‘undef‘,
   8     ‘defined‘,
   9     ‘specified‘
  10 ], function (prop) {
  11     //Reference from contexts instead of early binding to default context,
  12     //so that during builds, the latest instance of the default context
  13     //with its config gets used.
  14     req[prop] = function () {
  15         var ctx = contexts[defContextName];
  16         return ctx.require[prop].apply(ctx, arguments);
  17     };
  18 });
  19
  20 if (isBrowser && !cfg.skipDataMain) {}  //req.deps[mainscript]
  21
  22
  23 //Set up with config info.
  24 req(cfg); //最后启动。 按照之前写的num 一步一步的去加载。
  25
  26 /*----------------------------------------start---------------------------------*/
  27 //第一次     num == 2
  28 //params
  29
  30 var deps = {},
  31     callback = undefined,
  32     errback = undefined,
  33     optional = undefined;
  34
  35
  36 //--------------声明------------------
  37 var context = undefined,
  38     config = undefined,
  39     contextName = defContextName;
  40
  41 //-------------判断---------------
  42
  43 config = {};
  44 deps = [];
  45
  46 //------------判断--------------
  47 context = contexts[contextName] = req.s.newContext(contextName);  //跳到num ==3
  48
  49 //时间上就是执行  localRequire(deps, callback, errback);
  50 context.require(deps, callback, errback);  //跳到 num ==5
  51
  52
  53 /*---------------------------------------end-------------------------------*/
  54 /*
  55 *
  56 *
  57 * */
  58 /*---------------------------------------start-------------------------------*/
  59 //-----------------------进入核心函数--------------------------
  60 //第一次
  61 //function newContext(contextName)   num == 3
  62 context = {
  63     config: config,
  64     contextName: contextName,
  65     registry: registry,
  66     defined: defined,
  67     urlFetched: urlFetched,
  68     defQueue: defQueue,
  69     defQueueMap: {},
  70     Module: Module,
  71     makeModuleMap: makeModuleMap,
  72     nextTick: req.nextTick,
  73     onError: onError,
  74
  75     /**
  76      * Set a configuration for the context.
  77      * @param {Object} cfg config object to integrate.
  78      */
  79     configure: function (cfg) {
  80         //Make sure the baseUrl ends in a slash.
  81         if (cfg.baseUrl) {
  82             if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== ‘/‘) {
  83                 cfg.baseUrl += ‘/‘;
  84             }
  85         }
  86
  87         // Convert old style urlArgs string to a function.
  88         if (typeof cfg.urlArgs === ‘string‘) {
  89             var urlArgs = cfg.urlArgs;
  90             cfg.urlArgs = function(id, url) {
  91                 return (url.indexOf(‘?‘) === -1 ? ‘?‘ : ‘&‘) + urlArgs;
  92             };
  93         }
  94
  95         //Save off the paths since they require special processing,
  96         //they are additive.
  97         var shim = config.shim,
  98             objs = {
  99                 paths: true,
 100                 bundles: true,
 101                 config: true,
 102                 map: true
 103             };
 104
 105         eachProp(cfg, function (value, prop) {
 106             if (objs[prop]) {
 107                 if (!config[prop]) {
 108                     config[prop] = {};
 109                 }
 110                 mixin(config[prop], value, true, true);
 111             } else {
 112                 config[prop] = value;
 113             }
 114         });
 115
 116         //Reverse map the bundles
 117         if (cfg.bundles) {
 118             eachProp(cfg.bundles, function (value, prop) {
 119                 each(value, function (v) {
 120                     if (v !== prop) {
 121                         bundlesMap[v] = prop;
 122                     }
 123                 });
 124             });
 125         }
 126
 127         //Merge shim
 128         if (cfg.shim) {
 129             eachProp(cfg.shim, function (value, id) {
 130                 //Normalize the structure
 131                 if (isArray(value)) {
 132                     value = {
 133                         deps: value
 134                     };
 135                 }
 136                 if ((value.exports || value.init) && !value.exportsFn) {
 137                     value.exportsFn = context.makeShimExports(value);
 138                 }
 139                 shim[id] = value;
 140             });
 141             config.shim = shim;
 142         }
 143
 144         //Adjust packages if necessary.
 145         if (cfg.packages) {
 146             each(cfg.packages, function (pkgObj) {
 147                 var location, name;
 148
 149                 pkgObj = typeof pkgObj === ‘string‘ ? {name: pkgObj} : pkgObj;
 150
 151                 name = pkgObj.name;
 152                 location = pkgObj.location;
 153                 if (location) {
 154                     config.paths[name] = pkgObj.location;
 155                 }
 156
 157                 //Save pointer to main module ID for pkg name.
 158                 //Remove leading dot in main, so main paths are normalized,
 159                 //and remove any trailing .js, since different package
 160                 //envs have different conventions: some use a module name,
 161                 //some use a file name.
 162                 config.pkgs[name] = pkgObj.name + ‘/‘ + (pkgObj.main || ‘main‘)
 163                         .replace(currDirRegExp, ‘‘)
 164                         .replace(jsSuffixRegExp, ‘‘);
 165             });
 166         }
 167
 168         //If there are any "waiting to execute" modules in the registry,
 169         //update the maps for them, since their info, like URLs to load,
 170         //may have changed.
 171         eachProp(registry, function (mod, id) {
 172             //If module already has init called, since it is too
 173             //late to modify them, and ignore unnormalized ones
 174             //since they are transient.
 175             if (!mod.inited && !mod.map.unnormalized) {
 176                 mod.map = makeModuleMap(id, null, true);
 177             }
 178         });
 179
 180         //If a deps array or a config callback is specified, then call
 181         //require with those args. This is useful when require is defined as a
 182         //config object before require.js is loaded.
 183         if (cfg.deps || cfg.callback) {
 184             context.require(cfg.deps || [], cfg.callback);
 185         }
 186     },
 187
 188     makeShimExports: function (value) {
 189         function fn() {
 190             var ret;
 191             if (value.init) {
 192                 ret = value.init.apply(global, arguments);
 193             }
 194             return ret || (value.exports && getGlobal(value.exports));
 195         }
 196         return fn;
 197     },
 198
 199     makeRequire: function (relMap, options) {
 200         options = options || {};
 201
 202         function localRequire(deps, callback, errback) {
 203             var id, map, requireMod;
 204
 205             if (options.enableBuildCallback && callback && isFunction(callback)) {
 206                 callback.__requireJsBuild = true;
 207             }
 208
 209             if (typeof deps === ‘string‘) {
 210                 if (isFunction(callback)) {
 211                     //Invalid call
 212                     return onError(makeError(‘requireargs‘, ‘Invalid require call‘), errback);
 213                 }
 214
 215                 //If require|exports|module are requested, get the
 216                 //value for them from the special handlers. Caveat:
 217                 //this only works while module is being defined.
 218                 if (relMap && hasProp(handlers, deps)) {
 219                     return handlers[deps](registry[relMap.id]);
 220                 }
 221
 222                 //Synchronous access to one module. If require.get is
 223                 //available (as in the Node adapter), prefer that.
 224                 if (req.get) {
 225                     return req.get(context, deps, relMap, localRequire);
 226                 }
 227
 228                 //Normalize module name, if it contains . or ..
 229                 map = makeModuleMap(deps, relMap, false, true);
 230                 id = map.id;
 231
 232                 if (!hasProp(defined, id)) {
 233                     return onError(makeError(‘notloaded‘, ‘Module name "‘ +
 234                         id +
 235                         ‘" has not been loaded yet for context: ‘ +
 236                         contextName +
 237                         (relMap ? ‘‘ : ‘. Use require([])‘)));
 238                 }
 239                 return defined[id];
 240             }
 241
 242             //Grab defines waiting in the global queue.
 243             intakeDefines();
 244
 245             //Mark all the dependencies as needing to be loaded.
 246             context.nextTick(function () {
 247                 //Some defines could have been added since the
 248                 //require call, collect them.
 249                 intakeDefines();
 250
 251                 requireMod = getModule(makeModuleMap(null, relMap));
 252
 253                 //Store if map config should be applied to this require
 254                 //call for dependencies.
 255                 requireMod.skipMap = options.skipMap;
 256
 257                 requireMod.init(deps, callback, errback, {
 258                     enabled: true
 259                 });
 260
 261                 checkLoaded();
 262             });
 263
 264             return localRequire;
 265         }
 266
 267         mixin(localRequire, {
 268             isBrowser: isBrowser,
 269
 270             /**
 271              * Converts a module name + .extension into an URL path.
 272              * *Requires* the use of a module name. It does not support using
 273              * plain URLs like nameToUrl.
 274              */
 275             toUrl: function (moduleNamePlusExt) {
 276                 var ext,
 277                     index = moduleNamePlusExt.lastIndexOf(‘.‘),
 278                     segment = moduleNamePlusExt.split(‘/‘)[0],
 279                     isRelative = segment === ‘.‘ || segment === ‘..‘;
 280
 281                 //Have a file extension alias, and it is not the
 282                 //dots from a relative path.
 283                 if (index !== -1 && (!isRelative || index > 1)) {
 284                     ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
 285                     moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
 286                 }
 287
 288                 return context.nameToUrl(normalize(moduleNamePlusExt,
 289                     relMap && relMap.id, true), ext,  true);
 290             },
 291
 292             defined: function (id) {
 293                 return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
 294             },
 295
 296             specified: function (id) {
 297                 id = makeModuleMap(id, relMap, false, true).id;
 298                 return hasProp(defined, id) || hasProp(registry, id);
 299             }
 300         });
 301
 302         //Only allow undef on top level require calls
 303         if (!relMap) {
 304             localRequire.undef = function (id) {
 305                 //Bind any waiting define() calls to this context,
 306                 //fix for #408
 307                 takeGlobalQueue();
 308
 309                 var map = makeModuleMap(id, relMap, true),
 310                     mod = getOwn(registry, id);
 311
 312                 mod.undefed = true;
 313                 removeScript(id);
 314
 315                 delete defined[id];
 316                 delete urlFetched[map.url];
 317                 delete undefEvents[id];
 318
 319                 //Clean queued defines too. Go backwards
 320                 //in array so that the splices do not
 321                 //mess up the iteration.
 322                 eachReverse(defQueue, function(args, i) {
 323                     if (args[0] === id) {
 324                         defQueue.splice(i, 1);
 325                     }
 326                 });
 327                 delete context.defQueueMap[id];
 328
 329                 if (mod) {
 330                     //Hold on to listeners in case the
 331                     //module will be attempted to be reloaded
 332                     //using a different config.
 333                     if (mod.events.defined) {
 334                         undefEvents[id] = mod.events;
 335                     }
 336
 337                     cleanRegistry(id);
 338                 }
 339             };
 340         }
 341
 342         return localRequire;
 343     },
 344
 345     /**
 346      * Called to enable a module if it is still in the registry
 347      * awaiting enablement. A second arg, parent, the parent module,
 348      * is passed in for context, when this method is overridden by
 349      * the optimizer. Not shown here to keep code compact.
 350      */
 351     enable: function (depMap) {
 352         var mod = getOwn(registry, depMap.id);
 353         if (mod) {
 354             getModule(depMap).enable();
 355         }
 356     },
 357
 358     /**
 359      * Internal method used by environment adapters to complete a load event.
 360      * A load event could be a script load or just a load pass from a synchronous
 361      * load call.
 362      * @param {String} moduleName the name of the module to potentially complete.
 363      */
 364     completeLoad: function (moduleName) {
 365         var found, args, mod,
 366             shim = getOwn(config.shim, moduleName) || {},
 367             shExports = shim.exports;
 368
 369         takeGlobalQueue();
 370
 371         while (defQueue.length) {
 372             args = defQueue.shift();
 373             if (args[0] === null) {
 374                 args[0] = moduleName;
 375                 //If already found an anonymous module and bound it
 376                 //to this name, then this is some other anon module
 377                 //waiting for its completeLoad to fire.
 378                 if (found) {
 379                     break;
 380                 }
 381                 found = true;
 382             } else if (args[0] === moduleName) {
 383                 //Found matching define call for this script!
 384                 found = true;
 385             }
 386
 387             callGetModule(args);
 388         }
 389         context.defQueueMap = {};
 390
 391         //Do this after the cycle of callGetModule in case the result
 392         //of those calls/init calls changes the registry.
 393         mod = getOwn(registry, moduleName);
 394
 395         if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
 396             if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
 397                 if (hasPathFallback(moduleName)) {
 398                     return;
 399                 } else {
 400                     return onError(makeError(‘nodefine‘,
 401                         ‘No define call for ‘ + moduleName,
 402                         null,
 403                         [moduleName]));
 404                 }
 405             } else {
 406                 //A script that does not call define(), so just simulate
 407                 //the call for it.
 408                 callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
 409             }
 410         }
 411
 412         checkLoaded();
 413     },
 414
 415     /**
 416      * Converts a module name to a file path. Supports cases where
 417      * moduleName may actually be just an URL.
 418      * Note that it **does not** call normalize on the moduleName,
 419      * it is assumed to have already been normalized. This is an
 420      * internal API, not a public one. Use toUrl for the public API.
 421      */
 422     nameToUrl: function (moduleName, ext, skipExt) {
 423         var paths, syms, i, parentModule, url,
 424             parentPath, bundleId,
 425             pkgMain = getOwn(config.pkgs, moduleName);
 426
 427         if (pkgMain) {
 428             moduleName = pkgMain;
 429         }
 430
 431         bundleId = getOwn(bundlesMap, moduleName);
 432
 433         if (bundleId) {
 434             return context.nameToUrl(bundleId, ext, skipExt);
 435         }
 436
 437         //If a colon is in the URL, it indicates a protocol is used and it is just
 438         //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
 439         //or ends with .js, then assume the user meant to use an url and not a module id.
 440         //The slash is important for protocol-less URLs as well as full paths.
 441         if (req.jsExtRegExp.test(moduleName)) {
 442             //Just a plain path, not module name lookup, so just return it.
 443             //Add extension if it is included. This is a bit wonky, only non-.js things pass
 444             //an extension, this method probably needs to be reworked.
 445             url = moduleName + (ext || ‘‘);
 446         } else {
 447             //A module that needs to be converted to a path.
 448             paths = config.paths;
 449
 450             syms = moduleName.split(‘/‘);
 451             //For each module name segment, see if there is a path
 452             //registered for it. Start with most specific name
 453             //and work up from it.
 454             for (i = syms.length; i > 0; i -= 1) {
 455                 parentModule = syms.slice(0, i).join(‘/‘);
 456
 457                 parentPath = getOwn(paths, parentModule);
 458                 if (parentPath) {
 459                     //If an array, it means there are a few choices,
 460                     //Choose the one that is desired
 461                     if (isArray(parentPath)) {
 462                         parentPath = parentPath[0];
 463                     }
 464                     syms.splice(0, i, parentPath);
 465                     break;
 466                 }
 467             }
 468
 469             //Join the path parts together, then figure out if baseUrl is needed.
 470             url = syms.join(‘/‘);
 471             url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? ‘‘ : ‘.js‘));
 472             url = (url.charAt(0) === ‘/‘ || url.match(/^[\w\+\.\-]+:/) ? ‘‘ : config.baseUrl) + url;
 473         }
 474
 475         return config.urlArgs && !/^blob\:/.test(url) ?
 476         url + config.urlArgs(moduleName, url) : url;
 477     },
 478
 479     //Delegates to req.load. Broken out as a separate function to
 480     //allow overriding in the optimizer.
 481     load: function (id, url) {
 482         req.load(context, id, url);
 483     },
 484
 485     /**
 486      * Executes a module callback function. Broken out as a separate function
 487      * solely to allow the build system to sequence the files in the built
 488      * layer in the right sequence.
 489      *
 490      * @private
 491      */
 492     execCb: function (name, callback, args, exports) {
 493         return callback.apply(exports, args);
 494     },
 495
 496     /**
 497      * callback for script loads, used to check status of loading.
 498      *
 499      * @param {Event} evt the event from the browser for the script
 500      * that was loaded.
 501      */
 502     onScriptLoad: function (evt) {
 503         //Using currentTarget instead of target for Firefox 2.0‘s sake. Not
 504         //all old browsers will be supported, but this one was easy enough
 505         //to support and still makes sense.
 506         if (evt.type === ‘load‘ ||
 507             (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
 508             //Reset interactive script so a script node is not held onto for
 509             //to long.
 510             interactiveScript = null;
 511
 512             //Pull out the name of the module and the context.
 513             var data = getScriptData(evt);
 514             context.completeLoad(data.id);
 515         }
 516     },
 517
 518     /**
 519      * Callback for script errors.
 520      */
 521     onScriptError: function (evt) {
 522         var data = getScriptData(evt);
 523         if (!hasPathFallback(data.id)) {
 524             var parents = [];
 525             eachProp(registry, function(value, key) {
 526                 if (key.indexOf(‘[email protected]‘) !== 0) {
 527                     each(value.depMaps, function(depMap) {
 528                         if (depMap.id === data.id) {
 529                             parents.push(key);
 530                             return true;
 531                         }
 532                     });
 533                 }
 534             });
 535             return onError(makeError(‘scripterror‘, ‘Script error for "‘ + data.id +
 536                 (parents.length ?
 537                 ‘", needed by: ‘ + parents.join(‘, ‘) :
 538                     ‘"‘), evt, [data.id]));
 539         }
 540     }
 541 };
 542
 543 //得到一个闭包环境
 544 context.require = context.makeRequire();  //跳到num ===4
 545
 546 //return context;
 547 /*---------------------------------------end-------------------------------*/
 548 /*
 549 *
 550 *
 551 *
 552 *
 553 *
 554 * */
 555 /*---------------------------------------start-------------------------------*/
 556 //--------------------------进入makeRequire------------------------
 557 //第一次
 558 //params [relMap , options]   num == 4
 559
 560 var relMap = undefined,
 561      options = {};
 562
 563
 564 //声明localRequire函数
 565 var localRequire= function(deps, callback, errback){};
 566
 567 //给localRequire加属性
 568 var fn1={
 569     isBrowser: isBrowser,
 570
 571     /**
 572      * Converts a module name + .extension into an URL path.
 573      * *Requires* the use of a module name. It does not support using
 574      * plain URLs like nameToUrl.
 575      */
 576         toUrl: function (moduleNamePlusExt) {
 577     var ext,
 578         index = moduleNamePlusExt.lastIndexOf(‘.‘),
 579         segment = moduleNamePlusExt.split(‘/‘)[0],
 580         isRelative = segment === ‘.‘ || segment === ‘..‘;
 581
 582     //Have a file extension alias, and it is not the
 583     //dots from a relative path.
 584     if (index !== -1 && (!isRelative || index > 1)) {
 585         ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
 586         moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
 587     }
 588
 589     return context.nameToUrl(normalize(moduleNamePlusExt,
 590         relMap && relMap.id, true), ext,  true);
 591 },
 592
 593     defined: function (id) {
 594         return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
 595     },
 596
 597     specified: function (id) {
 598         id = makeModuleMap(id, relMap, false, true).id;
 599         return hasProp(defined, id) || hasProp(registry, id);
 600     }
 601 };
 602
 603
 604 //---------------------- 判断 if (!relMap)----------------------
 605
 606 //加属性
 607
 608 var fn2 =  undef = function(id){};
 609
 610 //返回return localRequire;
 611
 612 //总结一下 就是返回一个函数,给他加了一些属性;
 613 /*---------------------------------------end-------------------------------*/
 614 /*
 615 *
 616 * */
 617
 618 /*---------------------------------------start-------------------------------*/
 619 // num == 5
 620 intakeDefines() // 调到num == 6
 621 /*
 622 *    while (defQueue.length) {}遍历 defQueue;
 623 *
 624 *
 625 *
 626 * */
 627
 628 callGetModule(args); //args [id,deps,callb]  跳到num = 7
 629
 630 context.defQueueMap = {};
 631
 632 context.nextTick(function () {
 633     //Some defines could have been added since the
 634     //require call, collect them.
 635     intakeDefines();
 636
 637     requireMod = getModule(makeModuleMap(null, relMap));
 638
 639     //Store if map config should be applied to this require
 640     //call for dependencies.
 641     requireMod.skipMap = options.skipMap;
 642
 643     requireMod.init(deps, callback, errback, {
 644         enabled: true
 645     });
 646
 647     checkLoaded();
 648 });  //跳转到 12
 649
 650
 651 /*---------------------------------------end-------------------------------*/
 652 /*
 653 *
 654 *
 655 *
 656 *
 657 * */
 658 /*---------------------------------------start-------------------------------*/
 659 /* function takeGlobalQueue()   num == 6
 660  * */
 661
 662 //把globalDefQueue 里面通过define(id,desp,callback) 都放到  特定context 下的 defQueue
 663
 664 //并且最后清空   globalDefQueue = [];
 665
 666 /*---------------------------------------end-------------------------------*/
 667 /*
 668 *
 669 *
 670 *
 671 *
 672 * */
 673 /*---------------------------------------start-------------------------------*/
 674 //   function callGetModule(args)   num == 7
 675
 676 //将 defined里没有的 id进行构建模块
 677 if (!hasProp(defined, args[0])) {
 678     getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
 679 }
 680
 681 makeModuleMap(args[0], null, true) //跳转到 num== 8
 682
 683 getModule(makeModuleMap(args[0], null, true))  //跳转到 num == 9
 684
 685 getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);//跳转到 num == 11
 686 //生成的Module 里面的map属性 就是 makeModuleMap返回的对象。
 687
 688
 689 /*---------------------------------------end-------------------------------*/
 690 /*
 691 *
 692 *
 693 *
 694 *
 695 * */
 696 /*---------------------------------------start-------------------------------*/
 697
 698 //function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) //num == 8
 699
 700 //返回obj
 701 var obj =  {
 702     prefix: prefix,
 703     name: normalizedName,
 704     parentMap: parentModuleMap,
 705     unnormalized: !!suffix,
 706     url: url,
 707     originalName: originalName,
 708     isDefine: isDefine,
 709     id: (prefix ?
 710     prefix + ‘!‘ + normalizedName :
 711         normalizedName) + suffix
 712 };
 713
 714 /*---------------------------------------end-------------------------------*/
 715 /*
 716  *
 717  *
 718  *
 719  *
 720  * */
 721 /*-----------------------------------------start--------------------------------*/
 722
 723 //function getModule(depMap)   num == 9
 724 var id = depMap.id,
 725     mod = getOwn(registry, id);
 726
 727 if (!mod) {
 728     mod = registry[id] = new context.Module(depMap);
 729 }
 730
 731 new context.Module(depMap); //跳转到10
 732
 733 //return mod;
 734
 735 /*----------------------------------------end-------------------------*/
 736 /*
 737  *
 738  *
 739  *
 740  *
 741  * */
 742 /*-----------------------------------------start--------------------------------*/
 743 //num ===10
 744 Module = function (map) {
 745     this.events = getOwn(undefEvents, map.id) || {};
 746     this.map = map;
 747     this.shim = getOwn(config.shim, map.id);
 748     this.depExports = [];
 749     this.depMaps = [];
 750     this.depMatched = [];
 751     this.pluginMaps = {};
 752     this.depCount = 0;
 753
 754     /* this.exports this.factory
 755      this.depMaps = [],
 756      this.enabled, this.fetched
 757      */
 758 };
 759
 760 Module.prototype = {
 761     init: function (depMaps, factory, errback, options) {
 762         options = options || {};
 763
 764         //Do not do more inits if already done. Can happen if there
 765         //are multiple define calls for the same module. That is not
 766         //a normal, common case, but it is also not unexpected.
 767         if (this.inited) {
 768             return;
 769         }
 770
 771         this.factory = factory;
 772
 773         if (errback) {
 774             //Register for errors on this module.
 775             this.on(‘error‘, errback);
 776         } else if (this.events.error) {
 777             //If no errback already, but there are error listeners
 778             //on this module, set up an errback to pass to the deps.
 779             errback = bind(this, function (err) {
 780                 this.emit(‘error‘, err);
 781             });
 782         }
 783
 784         //Do a copy of the dependency array, so that
 785         //source inputs are not modified. For example
 786         //"shim" deps are passed in here directly, and
 787         //doing a direct modification of the depMaps array
 788         //would affect that config.
 789         this.depMaps = depMaps && depMaps.slice(0);
 790
 791         this.errback = errback;
 792
 793         //Indicate this module has be initialized
 794         this.inited = true;
 795
 796         this.ignore = options.ignore;
 797
 798         //Could have option to init this module in enabled mode,
 799         //or could have been previously marked as enabled. However,
 800         //the dependencies are not known until init is called. So
 801         //if enabled previously, now trigger dependencies as enabled.
 802         if (options.enabled || this.enabled) {
 803             //Enable this module and dependencies.
 804             //Will call this.check()
 805             this.enable();
 806         } else {
 807             this.check();
 808         }
 809     },
 810
 811     defineDep: function (i, depExports) {
 812         //Because of cycles, defined callback for a given
 813         //export can be called more than once.
 814         if (!this.depMatched[i]) {
 815             this.depMatched[i] = true;
 816             this.depCount -= 1;
 817             this.depExports[i] = depExports;
 818         }
 819     },
 820
 821     fetch: function () {
 822         if (this.fetched) {
 823             return;
 824         }
 825         this.fetched = true;
 826
 827         context.startTime = (new Date()).getTime();
 828
 829         var map = this.map;
 830
 831         //If the manager is for a plugin managed resource,
 832         //ask the plugin to load it now.
 833         if (this.shim) {
 834             context.makeRequire(this.map, {
 835                 enableBuildCallback: true
 836             })(this.shim.deps || [], bind(this, function () {
 837                 return map.prefix ? this.callPlugin() : this.load();
 838             }));
 839         } else {
 840             //Regular dependency.
 841             return map.prefix ? this.callPlugin() : this.load();
 842         }
 843     },
 844
 845     load: function () {
 846         var url = this.map.url;
 847
 848         //Regular dependency.
 849         if (!urlFetched[url]) {
 850             urlFetched[url] = true;
 851             context.load(this.map.id, url);
 852         }
 853     },
 854
 855     /**
 856      * Checks if the module is ready to define itself, and if so,
 857      * define it.
 858      */
 859     check: function () {
 860         if (!this.enabled || this.enabling) {
 861             return;
 862         }
 863
 864         var err, cjsModule,
 865             id = this.map.id,
 866             depExports = this.depExports,
 867             exports = this.exports,
 868             factory = this.factory;
 869
 870         if (!this.inited) {
 871             // Only fetch if not already in the defQueue.
 872             if (!hasProp(context.defQueueMap, id)) {
 873                 this.fetch();
 874             }
 875         } else if (this.error) {
 876             this.emit(‘error‘, this.error);
 877         } else if (!this.defining) {
 878             //The factory could trigger another require call
 879             //that would result in checking this module to
 880             //define itself again. If already in the process
 881             //of doing that, skip this work.
 882             this.defining = true;
 883
 884             if (this.depCount < 1 && !this.defined) {
 885                 if (isFunction(factory)) {
 886                     //If there is an error listener, favor passing
 887                     //to that instead of throwing an error. However,
 888                     //only do it for define()‘d  modules. require
 889                     //errbacks should not be called for failures in
 890                     //their callbacks (#699). However if a global
 891                     //onError is set, use that.
 892                     if ((this.events.error && this.map.isDefine) ||
 893                         req.onError !== defaultOnError) {
 894                         try {
 895                             exports = context.execCb(id, factory, depExports, exports);
 896                         } catch (e) {
 897                             err = e;
 898                         }
 899                     } else {
 900                         exports = context.execCb(id, factory, depExports, exports);
 901                     }
 902
 903                     // Favor return value over exports. If node/cjs in play,
 904                     // then will not have a return value anyway. Favor
 905                     // module.exports assignment over exports object.
 906                     if (this.map.isDefine && exports === undefined) {
 907                         cjsModule = this.module;
 908                         if (cjsModule) {
 909                             exports = cjsModule.exports;
 910                         } else if (this.usingExports) {
 911                             //exports already set the defined value.
 912                             exports = this.exports;
 913                         }
 914                     }
 915
 916                     if (err) {
 917                         err.requireMap = this.map;
 918                         err.requireModules = this.map.isDefine ? [this.map.id] : null;
 919                         err.requireType = this.map.isDefine ? ‘define‘ : ‘require‘;
 920                         return onError((this.error = err));
 921                     }
 922
 923                 } else {
 924                     //Just a literal value
 925                     exports = factory;
 926                 }
 927
 928                 this.exports = exports;
 929
 930                 if (this.map.isDefine && !this.ignore) {
 931                     defined[id] = exports;
 932
 933                     if (req.onResourceLoad) {
 934                         var resLoadMaps = [];
 935                         each(this.depMaps, function (depMap) {
 936                             resLoadMaps.push(depMap.normalizedMap || depMap);
 937                         });
 938                         req.onResourceLoad(context, this.map, resLoadMaps);
 939                     }
 940                 }
 941
 942                 //Clean up
 943                 cleanRegistry(id);
 944
 945                 this.defined = true;
 946             }
 947
 948             //Finished the define stage. Allow calling check again
 949             //to allow define notifications below in the case of a
 950             //cycle.
 951             this.defining = false;
 952
 953             if (this.defined && !this.defineEmitted) {
 954                 this.defineEmitted = true;
 955                 this.emit(‘defined‘, this.exports);
 956                 this.defineEmitComplete = true;
 957             }
 958
 959         }
 960     },
 961
 962     callPlugin: function () {
 963         var map = this.map,
 964             id = map.id,
 965         //Map already normalized the prefix.
 966             pluginMap = makeModuleMap(map.prefix);
 967
 968         //Mark this as a dependency for this plugin, so it
 969         //can be traced for cycles.
 970         this.depMaps.push(pluginMap);
 971
 972         on(pluginMap, ‘defined‘, bind(this, function (plugin) {
 973             var load, normalizedMap, normalizedMod,
 974                 bundleId = getOwn(bundlesMap, this.map.id),
 975                 name = this.map.name,
 976                 parentName = this.map.parentMap ? this.map.parentMap.name : null,
 977                 localRequire = context.makeRequire(map.parentMap, {
 978                     enableBuildCallback: true
 979                 });
 980
 981             //If current map is not normalized, wait for that
 982             //normalized name to load instead of continuing.
 983             if (this.map.unnormalized) {
 984                 //Normalize the ID if the plugin allows it.
 985                 if (plugin.normalize) {
 986                     name = plugin.normalize(name, function (name) {
 987                             return normalize(name, parentName, true);
 988                         }) || ‘‘;
 989                 }
 990
 991                 //prefix and name should already be normalized, no need
 992                 //for applying map config again either.
 993                 normalizedMap = makeModuleMap(map.prefix + ‘!‘ + name,
 994                     this.map.parentMap);
 995                 on(normalizedMap,
 996                     ‘defined‘, bind(this, function (value) {
 997                         this.map.normalizedMap = normalizedMap;
 998                         this.init([], function () { return value; }, null, {
 999                             enabled: true,
1000                             ignore: true
1001                         });
1002                     }));
1003
1004                 normalizedMod = getOwn(registry, normalizedMap.id);
1005                 if (normalizedMod) {
1006                     //Mark this as a dependency for this plugin, so it
1007                     //can be traced for cycles.
1008                     this.depMaps.push(normalizedMap);
1009
1010                     if (this.events.error) {
1011                         normalizedMod.on(‘error‘, bind(this, function (err) {
1012                             this.emit(‘error‘, err);
1013                         }));
1014                     }
1015                     normalizedMod.enable();
1016                 }
1017
1018                 return;
1019             }
1020
1021             //If a paths config, then just load that file instead to
1022             //resolve the plugin, as it is built into that paths layer.
1023             if (bundleId) {
1024                 this.map.url = context.nameToUrl(bundleId);
1025                 this.load();
1026                 return;
1027             }
1028
1029             load = bind(this, function (value) {
1030                 this.init([], function () { return value; }, null, {
1031                     enabled: true
1032                 });
1033             });
1034
1035             load.error = bind(this, function (err) {
1036                 this.inited = true;
1037                 this.error = err;
1038                 err.requireModules = [id];
1039
1040                 //Remove temp unnormalized modules for this module,
1041                 //since they will never be resolved otherwise now.
1042                 eachProp(registry, function (mod) {
1043                     if (mod.map.id.indexOf(id + ‘_unnormalized‘) === 0) {
1044                         cleanRegistry(mod.map.id);
1045                     }
1046                 });
1047
1048                 onError(err);
1049             });
1050
1051             //Allow plugins to load other code without having to know the
1052             //context or how to ‘complete‘ the load.
1053             load.fromText = bind(this, function (text, textAlt) {
1054                 /*jslint evil: true */
1055                 var moduleName = map.name,
1056                     moduleMap = makeModuleMap(moduleName),
1057                     hasInteractive = useInteractive;
1058
1059                 //As of 2.1.0, support just passing the text, to reinforce
1060                 //fromText only being called once per resource. Still
1061                 //support old style of passing moduleName but discard
1062                 //that moduleName in favor of the internal ref.
1063                 if (textAlt) {
1064                     text = textAlt;
1065                 }
1066
1067                 //Turn off interactive script matching for IE for any define
1068                 //calls in the text, then turn it back on at the end.
1069                 if (hasInteractive) {
1070                     useInteractive = false;
1071                 }
1072
1073                 //Prime the system by creating a module instance for
1074                 //it.
1075                 getModule(moduleMap);
1076
1077                 //Transfer any config to this other module.
1078                 if (hasProp(config.config, id)) {
1079                     config.config[moduleName] = config.config[id];
1080                 }
1081
1082                 try {
1083                     req.exec(text);
1084                 } catch (e) {
1085                     return onError(makeError(‘fromtexteval‘,
1086                         ‘fromText eval for ‘ + id +
1087                         ‘ failed: ‘ + e,
1088                         e,
1089                         [id]));
1090                 }
1091
1092                 if (hasInteractive) {
1093                     useInteractive = true;
1094                 }
1095
1096                 //Mark this as a dependency for the plugin
1097                 //resource
1098                 this.depMaps.push(moduleMap);
1099
1100                 //Support anonymous modules.
1101                 context.completeLoad(moduleName);
1102
1103                 //Bind the value of that module to the value for this
1104                 //resource ID.
1105                 localRequire([moduleName], load);
1106             });
1107
1108             //Use parentName here since the plugin‘s name is not reliable,
1109             //could be some weird string with no path that actually wants to
1110             //reference the parentName‘s path.
1111             plugin.load(map.name, localRequire, load, config);
1112         }));
1113
1114         context.enable(pluginMap, this);
1115         this.pluginMaps[pluginMap.id] = pluginMap;
1116     },
1117
1118     enable: function () {
1119         enabledRegistry[this.map.id] = this;
1120         this.enabled = true;
1121
1122         //Set flag mentioning that the module is enabling,
1123         //so that immediate calls to the defined callbacks
1124         //for dependencies do not trigger inadvertent load
1125         //with the depCount still being zero.
1126         this.enabling = true;
1127
1128         //Enable each dependency
1129         each(this.depMaps, bind(this, function (depMap, i) {
1130             var id, mod, handler;
1131
1132             if (typeof depMap === ‘string‘) {
1133                 //Dependency needs to be converted to a depMap
1134                 //and wired up to this module.
1135                 depMap = makeModuleMap(depMap,
1136                     (this.map.isDefine ? this.map : this.map.parentMap),
1137                     false,
1138                     !this.skipMap);
1139                 this.depMaps[i] = depMap;
1140
1141                 handler = getOwn(handlers, depMap.id);
1142
1143                 if (handler) {
1144                     this.depExports[i] = handler(this);
1145                     return;
1146                 }
1147
1148                 this.depCount += 1;
1149
1150                 on(depMap, ‘defined‘, bind(this, function (depExports) {
1151                     if (this.undefed) {
1152                         return;
1153                     }
1154                     this.defineDep(i, depExports);
1155                     this.check();
1156                 }));
1157
1158                 if (this.errback) {
1159                     on(depMap, ‘error‘, bind(this, this.errback));
1160                 } else if (this.events.error) {
1161                     // No direct errback on this module, but something
1162                     // else is listening for errors, so be sure to
1163                     // propagate the error correctly.
1164                     on(depMap, ‘error‘, bind(this, function(err) {
1165                         this.emit(‘error‘, err);
1166                     }));
1167                 }
1168             }
1169
1170             id = depMap.id;
1171             mod = registry[id];
1172
1173             //Skip special modules like ‘require‘, ‘exports‘, ‘module‘
1174             //Also, don‘t call enable if it is already enabled,
1175             //important in circular dependency cases.
1176             if (!hasProp(handlers, id) && mod && !mod.enabled) {
1177                 context.enable(depMap, this);
1178             }
1179         }));
1180
1181         //Enable each plugin that is used in
1182         //a dependency
1183         eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1184             var mod = getOwn(registry, pluginMap.id);
1185             if (mod && !mod.enabled) {
1186                 context.enable(pluginMap, this);
1187             }
1188         }));
1189
1190         this.enabling = false;
1191
1192         this.check();
1193     },
1194
1195     on: function (name, cb) {
1196         var cbs = this.events[name];
1197         if (!cbs) {
1198             cbs = this.events[name] = [];
1199         }
1200         cbs.push(cb);
1201     },
1202
1203     emit: function (name, evt) {
1204         each(this.events[name], function (cb) {
1205             cb(evt);
1206         });
1207         if (name === ‘error‘) {
1208             //Now that the error handler was triggered, remove
1209             //the listeners, since this broken Module instance
1210             //can stay around for a while in the registry.
1211             delete this.events[name];
1212         }
1213     }
1214 };
1215
1216 /*-----------------------------------------end--------------------------------*/
1217 /*
1218 *
1219 *
1220 *
1221 * */
1222 /*-----------------------------------------start--------------------------------*/
1223 //num = 11
1224
1225 //init: function (depMaps, factory, errback, options) {}
1226
1227 this.factory = factory;
1228 this.depMaps = depMaps && depMaps.slice(0);
1229
1230 this.errback = errback;
1231
1232 //Indicate this module has be initialized
1233 this.inited = true;
1234
1235 this.ignore = options.ignore;
1236
1237 //总结一句话  就是给module.绑定数据。
1238 /*----------------------------------------end-------------------------*/
1239 /*
1240  *
1241  * */
1242 /*----------------------------------------start-------------------------*/
1243 num == 12
1244
1245
1246 /*----------------------------------------end-------------------------*/
1247 /*
1248  *
1249  * */
/*---------------------------------------start-------------------------------*/req({}); // num == 1 跳到 num == 2

//Exports some context-sensitive methods on global require.each([    ‘toUrl‘,    ‘undef‘,    ‘defined‘,    ‘specified‘], function (prop) {    //Reference from contexts instead of early binding to default context,    //so that during builds, the latest instance of the default context    //with its config gets used.req[prop] = function () {        var ctx = contexts[defContextName];        return ctx.require[prop].apply(ctx, arguments);    };});

if (isBrowser && !cfg.skipDataMain) {}  //req.deps[mainscript]

//Set up with config info.req(cfg); //最后启动。 按照之前写的num 一步一步的去加载。

/*----------------------------------------start---------------------------------*///第一次     num == 2//params

var deps = {},    callback = undefined,    errback = undefined,    optional = undefined;

//--------------声明------------------var context = undefined,    config = undefined,    contextName = defContextName;

//-------------判断---------------

config = {};deps = [];

//------------判断--------------context = contexts[contextName] = req.s.newContext(contextName);  //跳到num ==3

//时间上就是执行  localRequire(deps, callback, errback);context.require(deps, callback, errback);  //跳到 num ==5

/*---------------------------------------end-------------------------------*//**** *//*---------------------------------------start-------------------------------*///-----------------------进入核心函数--------------------------//第一次//function newContext(contextName)   num == 3context = {    config: config,    contextName: contextName,    registry: registry,    defined: defined,    urlFetched: urlFetched,    defQueue: defQueue,    defQueueMap: {},    Module: Module,    makeModuleMap: makeModuleMap,    nextTick: req.nextTick,    onError: onError,

/**     * Set a configuration for the context.     * @param {Object} cfg config object to integrate.     */configure: function (cfg) {        //Make sure the baseUrl ends in a slash.if (cfg.baseUrl) {            if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== ‘/‘) {                cfg.baseUrl += ‘/‘;            }        }

// Convert old style urlArgs string to a function.if (typeof cfg.urlArgs === ‘string‘) {            var urlArgs = cfg.urlArgs;            cfg.urlArgs = function(id, url) {                return (url.indexOf(‘?‘) === -1 ? ‘?‘ : ‘&‘) + urlArgs;            };        }

//Save off the paths since they require special processing,        //they are additive.var shim = config.shim,            objs = {                paths: true,                bundles: true,                config: true,                map: true};

eachProp(cfg, function (value, prop) {            if (objs[prop]) {                if (!config[prop]) {                    config[prop] = {};                }                mixin(config[prop], value, true, true);            } else {                config[prop] = value;            }        });

//Reverse map the bundlesif (cfg.bundles) {            eachProp(cfg.bundles, function (value, prop) {                each(value, function (v) {                    if (v !== prop) {                        bundlesMap[v] = prop;                    }                });            });        }

//Merge shimif (cfg.shim) {            eachProp(cfg.shim, function (value, id) {                //Normalize the structureif (isArray(value)) {                    value = {                        deps: value                    };                }                if ((value.exports || value.init) && !value.exportsFn) {                    value.exportsFn = context.makeShimExports(value);                }                shim[id] = value;            });            config.shim = shim;        }

//Adjust packages if necessary.if (cfg.packages) {            each(cfg.packages, function (pkgObj) {                var location, name;

pkgObj = typeof pkgObj === ‘string‘ ? {name: pkgObj} : pkgObj;

name = pkgObj.name;                location = pkgObj.location;                if (location) {                    config.paths[name] = pkgObj.location;                }

//Save pointer to main module ID for pkg name.                //Remove leading dot in main, so main paths are normalized,                //and remove any trailing .js, since different package                //envs have different conventions: some use a module name,                //some use a file name.config.pkgs[name] = pkgObj.name + ‘/‘ + (pkgObj.main || ‘main‘)                        .replace(currDirRegExp, ‘‘)                        .replace(jsSuffixRegExp, ‘‘);            });        }

//If there are any "waiting to execute" modules in the registry,        //update the maps for them, since their info, like URLs to load,        //may have changed.eachProp(registry, function (mod, id) {            //If module already has init called, since it is too            //late to modify them, and ignore unnormalized ones            //since they are transient.if (!mod.inited && !mod.map.unnormalized) {                mod.map = makeModuleMap(id, null, true);            }        });

//If a deps array or a config callback is specified, then call        //require with those args. This is useful when require is defined as a        //config object before require.js is loaded.if (cfg.deps || cfg.callback) {            context.require(cfg.deps || [], cfg.callback);        }    },

makeShimExports: function (value) {        function fn() {            var ret;            if (value.init) {                ret = value.init.apply(global, arguments);            }            return ret || (value.exports && getGlobal(value.exports));        }        return fn;    },

makeRequire: function (relMap, options) {        options = options || {};

function localRequire(deps, callback, errback) {            var id, map, requireMod;

if (options.enableBuildCallback && callback && isFunction(callback)) {                callback.__requireJsBuild = true;            }

if (typeof deps === ‘string‘) {                if (isFunction(callback)) {                    //Invalid callreturn onError(makeError(‘requireargs‘, ‘Invalid require call‘), errback);                }

//If require|exports|module are requested, get the                //value for them from the special handlers. Caveat:                //this only works while module is being defined.if (relMap && hasProp(handlers, deps)) {                    return handlers[deps](registry[relMap.id]);                }

//Synchronous access to one module. If require.get is                //available (as in the Node adapter), prefer that.if (req.get) {                    return req.get(context, deps, relMap, localRequire);                }

//Normalize module name, if it contains . or ..map = makeModuleMap(deps, relMap, false, true);                id = map.id;

if (!hasProp(defined, id)) {                    return onError(makeError(‘notloaded‘, ‘Module name "‘ +                        id +                        ‘" has not been loaded yet for context: ‘ +                        contextName +                        (relMap ? ‘‘ : ‘. Use require([])‘)));                }                return defined[id];            }

//Grab defines waiting in the global queue.intakeDefines();

//Mark all the dependencies as needing to be loaded.context.nextTick(function () {                //Some defines could have been added since the                //require call, collect them.intakeDefines();

requireMod = getModule(makeModuleMap(null, relMap));

//Store if map config should be applied to this require                //call for dependencies.requireMod.skipMap = options.skipMap;

requireMod.init(deps, callback, errback, {                    enabled: true});

checkLoaded();            });

return localRequire;        }

mixin(localRequire, {            isBrowser: isBrowser,

/**             * Converts a module name + .extension into an URL path.             * *Requires* the use of a module name. It does not support using             * plain URLs like nameToUrl.             */toUrl: function (moduleNamePlusExt) {                var ext,                    index = moduleNamePlusExt.lastIndexOf(‘.‘),                    segment = moduleNamePlusExt.split(‘/‘)[0],                    isRelative = segment === ‘.‘ || segment === ‘..‘;

//Have a file extension alias, and it is not the                //dots from a relative path.if (index !== -1 && (!isRelative || index > 1)) {                    ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);                    moduleNamePlusExt = moduleNamePlusExt.substring(0, index);                }

return context.nameToUrl(normalize(moduleNamePlusExt,                    relMap && relMap.id, true), ext,  true);            },

defined: function (id) {                return hasProp(defined, makeModuleMap(id, relMap, false, true).id);            },

specified: function (id) {                id = makeModuleMap(id, relMap, false, true).id;                return hasProp(defined, id) || hasProp(registry, id);            }        });

//Only allow undef on top level require callsif (!relMap) {            localRequire.undef = function (id) {                //Bind any waiting define() calls to this context,                //fix for #408takeGlobalQueue();

var map = makeModuleMap(id, relMap, true),                    mod = getOwn(registry, id);

mod.undefed = true;                removeScript(id);

delete defined[id];                delete urlFetched[map.url];                delete undefEvents[id];

//Clean queued defines too. Go backwards                //in array so that the splices do not                //mess up the iteration.eachReverse(defQueue, function(args, i) {                    if (args[0] === id) {                        defQueue.splice(i, 1);                    }                });                delete context.defQueueMap[id];

if (mod) {                    //Hold on to listeners in case the                    //module will be attempted to be reloaded                    //using a different config.if (mod.events.defined) {                        undefEvents[id] = mod.events;                    }

cleanRegistry(id);                }            };        }

return localRequire;    },

/**     * Called to enable a module if it is still in the registry     * awaiting enablement. A second arg, parent, the parent module,     * is passed in for context, when this method is overridden by     * the optimizer. Not shown here to keep code compact.     */enable: function (depMap) {        var mod = getOwn(registry, depMap.id);        if (mod) {            getModule(depMap).enable();        }    },

/**     * Internal method used by environment adapters to complete a load event.     * A load event could be a script load or just a load pass from a synchronous     * load call.     * @param {String} moduleName the name of the module to potentially complete.     */completeLoad: function (moduleName) {        var found, args, mod,            shim = getOwn(config.shim, moduleName) || {},            shExports = shim.exports;

takeGlobalQueue();

while (defQueue.length) {            args = defQueue.shift();            if (args[0] === null) {                args[0] = moduleName;                //If already found an anonymous module and bound it                //to this name, then this is some other anon module                //waiting for its completeLoad to fire.if (found) {                    break;                }                found = true;            } else if (args[0] === moduleName) {                //Found matching define call for this script!found = true;            }

callGetModule(args);        }        context.defQueueMap = {};

//Do this after the cycle of callGetModule in case the result        //of those calls/init calls changes the registry.mod = getOwn(registry, moduleName);

if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {            if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {                if (hasPathFallback(moduleName)) {                    return;                } else {                    return onError(makeError(‘nodefine‘,                        ‘No define call for ‘ + moduleName,                        null,                        [moduleName]));                }            } else {                //A script that does not call define(), so just simulate                //the call for it.callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);            }        }

checkLoaded();    },

/**     * Converts a module name to a file path. Supports cases where     * moduleName may actually be just an URL.     * Note that it **does not** call normalize on the moduleName,     * it is assumed to have already been normalized. This is an     * internal API, not a public one. Use toUrl for the public API.     */nameToUrl: function (moduleName, ext, skipExt) {        var paths, syms, i, parentModule, url,            parentPath, bundleId,            pkgMain = getOwn(config.pkgs, moduleName);

if (pkgMain) {            moduleName = pkgMain;        }

bundleId = getOwn(bundlesMap, moduleName);

if (bundleId) {            return context.nameToUrl(bundleId, ext, skipExt);        }

//If a colon is in the URL, it indicates a protocol is used and it is just        //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)        //or ends with .js, then assume the user meant to use an url and not a module id.        //The slash is important for protocol-less URLs as well as full paths.if (req.jsExtRegExp.test(moduleName)) {            //Just a plain path, not module name lookup, so just return it.            //Add extension if it is included. This is a bit wonky, only non-.js things pass            //an extension, this method probably needs to be reworked.url = moduleName + (ext || ‘‘);        } else {            //A module that needs to be converted to a path.paths = config.paths;

syms = moduleName.split(‘/‘);            //For each module name segment, see if there is a path            //registered for it. Start with most specific name            //and work up from it.for (i = syms.length; i > 0; i -= 1) {                parentModule = syms.slice(0, i).join(‘/‘);

parentPath = getOwn(paths, parentModule);                if (parentPath) {                    //If an array, it means there are a few choices,                    //Choose the one that is desiredif (isArray(parentPath)) {                        parentPath = parentPath[0];                    }                    syms.splice(0, i, parentPath);                    break;                }            }

//Join the path parts together, then figure out if baseUrl is needed.url = syms.join(‘/‘);            url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? ‘‘ : ‘.js‘));            url = (url.charAt(0) === ‘/‘ || url.match(/^[\w\+\.\-]+:/) ? ‘‘ : config.baseUrl) + url;        }

return config.urlArgs && !/^blob\:/.test(url) ?        url + config.urlArgs(moduleName, url) : url;    },

//Delegates to req.load. Broken out as a separate function to    //allow overriding in the optimizer.load: function (id, url) {        req.load(context, id, url);    },

/**     * Executes a module callback function. Broken out as a separate function     * solely to allow the build system to sequence the files in the built     * layer in the right sequence.     *     * @private*/execCb: function (name, callback, args, exports) {        return callback.apply(exports, args);    },

/**     * callback for script loads, used to check status of loading.     *     * @param {Event} evt the event from the browser for the script     * that was loaded.     */onScriptLoad: function (evt) {        //Using currentTarget instead of target for Firefox 2.0‘s sake. Not        //all old browsers will be supported, but this one was easy enough        //to support and still makes sense.if (evt.type === ‘load‘ ||            (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {            //Reset interactive script so a script node is not held onto for            //to long.interactiveScript = null;

//Pull out the name of the module and the context.var data = getScriptData(evt);            context.completeLoad(data.id);        }    },

/**     * Callback for script errors.     */onScriptError: function (evt) {        var data = getScriptData(evt);        if (!hasPathFallback(data.id)) {            var parents = [];            eachProp(registry, function(value, key) {                if (key.indexOf(‘[email protected]‘) !== 0) {                    each(value.depMaps, function(depMap) {                        if (depMap.id === data.id) {                            parents.push(key);                            return true;                        }                    });                }            });            return onError(makeError(‘scripterror‘, ‘Script error for "‘ + data.id +                (parents.length ?                ‘", needed by: ‘ + parents.join(‘, ‘) :                    ‘"‘), evt, [data.id]));        }    }};

//得到一个闭包环境context.require = context.makeRequire();  //跳到num ===4

//return context;/*---------------------------------------end-------------------------------*//******* *//*---------------------------------------start-------------------------------*///--------------------------进入makeRequire------------------------//第一次//params [relMap , options]   num == 4

var relMap = undefined,     options = {};

//声明localRequire函数var localRequire= function(deps, callback, errback){};

//给localRequire加属性var fn1={    isBrowser: isBrowser,

/**     * Converts a module name + .extension into an URL path.     * *Requires* the use of a module name. It does not support using     * plain URLs like nameToUrl.     */toUrl: function (moduleNamePlusExt) {    var ext,        index = moduleNamePlusExt.lastIndexOf(‘.‘),        segment = moduleNamePlusExt.split(‘/‘)[0],        isRelative = segment === ‘.‘ || segment === ‘..‘;

//Have a file extension alias, and it is not the    //dots from a relative path.if (index !== -1 && (!isRelative || index > 1)) {        ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);        moduleNamePlusExt = moduleNamePlusExt.substring(0, index);    }

return context.nameToUrl(normalize(moduleNamePlusExt,        relMap && relMap.id, true), ext,  true);},

defined: function (id) {        return hasProp(defined, makeModuleMap(id, relMap, false, true).id);    },

specified: function (id) {        id = makeModuleMap(id, relMap, false, true).id;        return hasProp(defined, id) || hasProp(registry, id);    }};

//---------------------- 判断 if (!relMap)----------------------

//加属性

var fn2 =  undef = function(id){};

//返回return localRequire;

//总结一下 就是返回一个函数,给他加了一些属性;/*---------------------------------------end-------------------------------*//*** */

/*---------------------------------------start-------------------------------*/// num == 5intakeDefines() // 调到num == 6/**    while (defQueue.length) {}遍历 defQueue;**** */

callGetModule(args); //args [id,deps,callb]  跳到num = 7

context.defQueueMap = {};

context.nextTick(function () {    //Some defines could have been added since the    //require call, collect them.intakeDefines();

requireMod = getModule(makeModuleMap(null, relMap));

//Store if map config should be applied to this require    //call for dependencies.requireMod.skipMap = options.skipMap;

requireMod.init(deps, callback, errback, {        enabled: true});

checkLoaded();});  //跳转到 12

/*---------------------------------------end-------------------------------*//****** *//*---------------------------------------start-------------------------------*//* function takeGlobalQueue()   num == 6 * */

//把globalDefQueue 里面通过define(id,desp,callback) 都放到  特定context 下的 defQueue

//并且最后清空   globalDefQueue = [];

/*---------------------------------------end-------------------------------*//****** *//*---------------------------------------start-------------------------------*///   function callGetModule(args)   num == 7

//将 defined里没有的 id进行构建模块if (!hasProp(defined, args[0])) {    getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);}

makeModuleMap(args[0], null, true) //跳转到 num== 8

getModule(makeModuleMap(args[0], null, true))  //跳转到 num == 9

getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);//跳转到 num == 11//生成的Module 里面的map属性 就是 makeModuleMap返回的对象。

/*---------------------------------------end-------------------------------*//****** *//*---------------------------------------start-------------------------------*/

//function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) //num == 8

//返回objvar obj =  {    prefix: prefix,    name: normalizedName,    parentMap: parentModuleMap,    unnormalized: !!suffix,    url: url,    originalName: originalName,    isDefine: isDefine,    id: (prefix ?    prefix + ‘!‘ + normalizedName :        normalizedName) + suffix};

/*---------------------------------------end-------------------------------*//* * * * * * *//*-----------------------------------------start--------------------------------*/

//function getModule(depMap)   num == 9var id = depMap.id,    mod = getOwn(registry, id);

if (!mod) {    mod = registry[id] = new context.Module(depMap);}

new context.Module(depMap); //跳转到10

//return mod;

/*----------------------------------------end-------------------------*//* * * * * * *//*-----------------------------------------start--------------------------------*///num ===10Module = 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;

/* this.exports this.factory     this.depMaps = [],     this.enabled, this.fetched     */};

Module.prototype = {    init: function (depMaps, factory, errback, options) {        options = options || {};

//Do not do more inits if already done. Can happen if there        //are multiple define calls for the same module. That is not        //a normal, common case, but it is also not unexpected.if (this.inited) {            return;        }

this.factory = factory;

if (errback) {            //Register for errors on this module.this.on(‘error‘, errback);        } else if (this.events.error) {            //If no errback already, but there are error listeners            //on this module, set up an errback to pass to the deps.errback = bind(this, function (err) {                this.emit(‘error‘, err);            });        }

//Do a copy of the dependency array, so that        //source inputs are not modified. For example        //"shim" deps are passed in here directly, and        //doing a direct modification of the depMaps array        //would affect that config.this.depMaps = depMaps && depMaps.slice(0);

this.errback = errback;

//Indicate this module has be initializedthis.inited = true;

this.ignore = options.ignore;

//Could have option to init this module in enabled mode,        //or could have been previously marked as enabled. However,        //the dependencies are not known until init is called. So        //if enabled previously, now trigger dependencies as enabled.if (options.enabled || this.enabled) {            //Enable this module and dependencies.            //Will call this.check()this.enable();        } else {            this.check();        }    },

defineDep: function (i, depExports) {        //Because of cycles, defined callback for a given        //export can be called more than once.if (!this.depMatched[i]) {            this.depMatched[i] = true;            this.depCount -= 1;            this.depExports[i] = depExports;        }    },

fetch: function () {        if (this.fetched) {            return;        }        this.fetched = true;

context.startTime = (new Date()).getTime();

var map = this.map;

//If the manager is for a plugin managed resource,        //ask the plugin to load it now.if (this.shim) {            context.makeRequire(this.map, {                enableBuildCallback: true})(this.shim.deps || [], bind(this, function () {                return map.prefix ? this.callPlugin() : this.load();            }));        } else {            //Regular dependency.return map.prefix ? this.callPlugin() : this.load();        }    },

load: function () {        var url = this.map.url;

//Regular dependency.if (!urlFetched[url]) {            urlFetched[url] = true;            context.load(this.map.id, url);        }    },

/**     * Checks if the module is ready to define itself, and if so,     * define it.     */check: function () {        if (!this.enabled || this.enabling) {            return;        }

var err, cjsModule,            id = this.map.id,            depExports = this.depExports,            exports = this.exports,            factory = this.factory;

if (!this.inited) {            // Only fetch if not already in the defQueue.if (!hasProp(context.defQueueMap, id)) {                this.fetch();            }        } else if (this.error) {            this.emit(‘error‘, this.error);        } else if (!this.defining) {            //The factory could trigger another require call            //that would result in checking this module to            //define itself again. If already in the process            //of doing that, skip this work.this.defining = true;

if (this.depCount < 1 && !this.defined) {                if (isFunction(factory)) {                    //If there is an error listener, favor passing                    //to that instead of throwing an error. However,                    //only do it for define()‘d  modules. require                    //errbacks should not be called for failures in                    //their callbacks (#699). However if a global                    //onError is set, use that.if ((this.events.error && this.map.isDefine) ||                        req.onError !== defaultOnError) {                        try {                            exports = context.execCb(id, factory, depExports, exports);                        } catch (e) {                            err = e;                        }                    } else {                        exports = context.execCb(id, factory, depExports, exports);                    }

// Favor return value over exports. If node/cjs in play,                    // then will not have a return value anyway. Favor                    // module.exports assignment over exports object.if (this.map.isDefine && exports === undefined) {                        cjsModule = this.module;                        if (cjsModule) {                            exports = cjsModule.exports;                        } else if (this.usingExports) {                            //exports already set the defined value.exports = this.exports;                        }                    }

if (err) {                        err.requireMap = this.map;                        err.requireModules = this.map.isDefine ? [this.map.id] : null;                        err.requireType = this.map.isDefine ? ‘define‘ : ‘require‘;                        return onError((this.error = err));                    }

} else {                    //Just a literal valueexports = factory;                }

this.exports = exports;

if (this.map.isDefine && !this.ignore) {                    defined[id] = exports;

if (req.onResourceLoad) {                        var resLoadMaps = [];                        each(this.depMaps, function (depMap) {                            resLoadMaps.push(depMap.normalizedMap || depMap);                        });                        req.onResourceLoad(context, this.map, resLoadMaps);                    }                }

//Clean upcleanRegistry(id);

this.defined = true;            }

//Finished the define stage. Allow calling check again            //to allow define notifications below in the case of a            //cycle.this.defining = false;

if (this.defined && !this.defineEmitted) {                this.defineEmitted = true;                this.emit(‘defined‘, this.exports);                this.defineEmitComplete = true;            }

}    },

callPlugin: function () {        var map = this.map,            id = map.id,        //Map already normalized the prefix.pluginMap = makeModuleMap(map.prefix);

//Mark this as a dependency for this plugin, so it        //can be traced for cycles.this.depMaps.push(pluginMap);

on(pluginMap, ‘defined‘, bind(this, function (plugin) {            var load, normalizedMap, normalizedMod,                bundleId = getOwn(bundlesMap, this.map.id),                name = this.map.name,                parentName = this.map.parentMap ? this.map.parentMap.name : null,                localRequire = context.makeRequire(map.parentMap, {                    enableBuildCallback: true});

//If current map is not normalized, wait for that            //normalized name to load instead of continuing.if (this.map.unnormalized) {                //Normalize the ID if the plugin allows it.if (plugin.normalize) {                    name = plugin.normalize(name, function (name) {                            return normalize(name, parentName, true);                        }) || ‘‘;                }

//prefix and name should already be normalized, no need                //for applying map config again either.normalizedMap = makeModuleMap(map.prefix + ‘!‘ + name,                    this.map.parentMap);                on(normalizedMap,                    ‘defined‘, bind(this, function (value) {                        this.map.normalizedMap = normalizedMap;                        this.init([], function () { return value; }, null, {                            enabled: true,                            ignore: true});                    }));

normalizedMod = getOwn(registry, normalizedMap.id);                if (normalizedMod) {                    //Mark this as a dependency for this plugin, so it                    //can be traced for cycles.this.depMaps.push(normalizedMap);

if (this.events.error) {                        normalizedMod.on(‘error‘, bind(this, function (err) {                            this.emit(‘error‘, err);                        }));                    }                    normalizedMod.enable();                }

return;            }

//If a paths config, then just load that file instead to            //resolve the plugin, as it is built into that paths layer.if (bundleId) {                this.map.url = context.nameToUrl(bundleId);                this.load();                return;            }

load = bind(this, function (value) {                this.init([], function () { return value; }, null, {                    enabled: true});            });

load.error = bind(this, function (err) {                this.inited = true;                this.error = err;                err.requireModules = [id];

//Remove temp unnormalized modules for this module,                //since they will never be resolved otherwise now.eachProp(registry, function (mod) {                    if (mod.map.id.indexOf(id + ‘_unnormalized‘) === 0) {                        cleanRegistry(mod.map.id);                    }                });

onError(err);            });

//Allow plugins to load other code without having to know the            //context or how to ‘complete‘ the load.load.fromText = bind(this, function (text, textAlt) {                /*jslint evil: true */var moduleName = map.name,                    moduleMap = makeModuleMap(moduleName),                    hasInteractive = useInteractive;

//As of 2.1.0, support just passing the text, to reinforce                //fromText only being called once per resource. Still                //support old style of passing moduleName but discard                //that moduleName in favor of the internal ref.if (textAlt) {                    text = textAlt;                }

//Turn off interactive script matching for IE for any define                //calls in the text, then turn it back on at the end.if (hasInteractive) {                    useInteractive = false;                }

//Prime the system by creating a module instance for                //it.getModule(moduleMap);

//Transfer any config to this other module.if (hasProp(config.config, id)) {                    config.config[moduleName] = config.config[id];                }

try {                    req.exec(text);                } catch (e) {                    return onError(makeError(‘fromtexteval‘,                        ‘fromText eval for ‘ + id +                        ‘ failed: ‘ + e,                        e,                        [id]));                }

if (hasInteractive) {                    useInteractive = true;                }

//Mark this as a dependency for the plugin                //resourcethis.depMaps.push(moduleMap);

//Support anonymous modules.context.completeLoad(moduleName);

//Bind the value of that module to the value for this                //resource ID.localRequire([moduleName], load);            });

//Use parentName here since the plugin‘s name is not reliable,            //could be some weird string with no path that actually wants to            //reference the parentName‘s path.plugin.load(map.name, localRequire, load, config);        }));

context.enable(pluginMap, this);        this.pluginMaps[pluginMap.id] = pluginMap;    },

enable: function () {        enabledRegistry[this.map.id] = this;        this.enabled = true;

//Set flag mentioning that the module is enabling,        //so that immediate calls to the defined callbacks        //for dependencies do not trigger inadvertent load        //with the depCount still being zero.this.enabling = true;

//Enable each dependencyeach(this.depMaps, bind(this, function (depMap, i) {            var id, mod, handler;

if (typeof depMap === ‘string‘) {                //Dependency needs to be converted to a depMap                //and wired up to this module.depMap = makeModuleMap(depMap,                    (this.map.isDefine ? this.map : this.map.parentMap),                    false,                    !this.skipMap);                this.depMaps[i] = depMap;

handler = getOwn(handlers, depMap.id);

if (handler) {                    this.depExports[i] = handler(this);                    return;                }

this.depCount += 1;

on(depMap, ‘defined‘, bind(this, function (depExports) {                    if (this.undefed) {                        return;                    }                    this.defineDep(i, depExports);                    this.check();                }));

if (this.errback) {                    on(depMap, ‘error‘, bind(this, this.errback));                } else if (this.events.error) {                    // No direct errback on this module, but something                    // else is listening for errors, so be sure to                    // propagate the error correctly.on(depMap, ‘error‘, bind(this, function(err) {                        this.emit(‘error‘, err);                    }));                }            }

id = depMap.id;            mod = registry[id];

//Skip special modules like ‘require‘, ‘exports‘, ‘module‘            //Also, don‘t call enable if it is already enabled,            //important in circular dependency cases.if (!hasProp(handlers, id) && mod && !mod.enabled) {                context.enable(depMap, this);            }        }));

//Enable each plugin that is used in        //a dependencyeachProp(this.pluginMaps, bind(this, function (pluginMap) {            var mod = getOwn(registry, pluginMap.id);            if (mod && !mod.enabled) {                context.enable(pluginMap, this);            }        }));

this.enabling = false;

this.check();    },

on: function (name, cb) {        var cbs = this.events[name];        if (!cbs) {            cbs = this.events[name] = [];        }        cbs.push(cb);    },

emit: function (name, evt) {        each(this.events[name], function (cb) {            cb(evt);        });        if (name === ‘error‘) {            //Now that the error handler was triggered, remove            //the listeners, since this broken Module instance            //can stay around for a while in the registry.delete this.events[name];        }    }};

/*-----------------------------------------end--------------------------------*//***** *//*-----------------------------------------start--------------------------------*///num = 11

//init: function (depMaps, factory, errback, options) {}

this.factory = factory;this.depMaps = depMaps && depMaps.slice(0);

this.errback = errback;

//Indicate this module has be initializedthis.inited = true;

this.ignore = options.ignore;

//总结一句话  就是给module.绑定数据。/*----------------------------------------end-------------------------*//* * * *//*----------------------------------------start-------------------------*/num == 12

/*----------------------------------------end-------------------------*//* * * */
时间: 2024-10-16 18:38:10

requirejs--源码分析的相关文章

requireJS源码分析

目录 1. requireJS概念 2. AMD与CMD区别 3. 模块加载器的来历 4. 模块加载器的利弊 5. 模块加载器的使用场景 6. requireJS源码解读 7.心得总结 一.requireJS概述 概述 RequireJS是一款遵循AMD规范协议的JavaScript模拟加载器. 业界常见模块加载器(labjs.requirejs.seajs) LABjs的核心是LAB(Loading and Blocking):核心价值是性能优化 至于requirejs和seajs区别,知乎上

RequireJs 源码解读及思考

写在前面: 最近做的一个项目,用的require和backbone,对两者的使用已经很熟悉了,但是一直都有好奇他们怎么实现的,一直寻思着读读源码.现在项目结束,终于有机会好好研究一下. 本文重要解读requirejs的源码,backbone源码分析将会随后给出. 行文思路: requirejs 基本介绍 requirejs使用后的几个好奇 requirejs源码解读 requirejs基本介绍 由于篇幅有限,这里不会详解requirejs的使用和api,建议读者朋友自己去用几次,再详读api.

ZRender源码分析2:Storage(Model层)

回顾 上一篇请移步:zrender源码分析1:总体结构 本篇进行ZRender的MVC结构中的M进行分析 总体理解 上篇说到,Storage负责MVC层中的Model,也就是模型,对于zrender来说,这个model就是shape对象,在1.x表现的还不强烈,到了2.x, 在zr.addShape()的时候,传入的参数就必须是new出来的对象了详情请看这里 2.x相比1.x的变化,关于这个变化多说点吧,那就是从1.x升级到2.x的时候,因为方式变了,总不能改掉所有的代码,总不能像ext一样,

TeamTalk源码分析之login_server

login_server是TeamTalk的登录服务器,负责分配一个负载较小的MsgServer给客户端使用,按照新版TeamTalk完整部署教程来配置的话,login_server的服务端口就是8080,客户端登录服务器地址配置如下(这里是win版本客户端): 1.login_server启动流程 login_server的启动是从login_server.cpp中的main函数开始的,login_server.cpp所在工程路径为server\src\login_server.下表是logi

Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)

1 背景 还记得前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>中关于透过源码继续进阶实例验证模块中存在的点击Button却触发了LinearLayout的事件疑惑吗?当时说了,在那一篇咱们只讨论View的触摸事件派发机制,这个疑惑留在了这一篇解释,也就是ViewGroup的事件派发机制. PS:阅读本篇前建议先查看前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>,这一篇承接上一篇. 关于View与ViewGroup的区别在前一篇的A

HashMap与TreeMap源码分析

1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Java这么久,也写过一些小项目,也使用过TreeMap无数次,但到现在才明白它的实现原理).因此本着"不要重复造轮子"的思想,就用这篇博客来记录分析TreeMap源码的过程,也顺便瞅一瞅HashMap. 2. 继承结构 (1) 继承结构 下面是HashMap与TreeMap的继承结构: pu

Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)【转】

原文地址:Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938395.html 前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化.在内核初始化函数start_kernel执行到最后,就是调用rest_init函数,这个函数的主要使命就是创建并启动内核线

Spark的Master和Worker集群启动的源码分析

基于spark1.3.1的源码进行分析 spark master启动源码分析 1.在start-master.sh调用master的main方法,main方法调用 def main(argStrings: Array[String]) { SignalLogger.register(log) val conf = new SparkConf val args = new MasterArguments(argStrings, conf) val (actorSystem, _, _, _) =

Solr4.8.0源码分析(22)之 SolrCloud的Recovery策略(三)

Solr4.8.0源码分析(22)之 SolrCloud的Recovery策略(三) 本文是SolrCloud的Recovery策略系列的第三篇文章,前面两篇主要介绍了Recovery的总体流程,以及PeerSync策略.本文以及后续的文章将重点介绍Replication策略.Replication策略不但可以在SolrCloud中起到leader到replica的数据同步,也可以在用多个单独的Solr来实现主从同步.本文先介绍在SolrCloud的leader到replica的数据同步,下一篇

zg手册 之 python2.7.7源码分析(4)-- pyc字节码文件

什么是字节码 python解释器在执行python脚本文件时,对文件中的python源代码进行编译,编译的结果就是byte code(字节码) python虚拟机执行编译好的字节码,完成程序的运行 python会为导入的模块创建字节码文件 字节码文件的创建过程 当a.py依赖b.py时,如在a.py中import b python先检查是否有b.pyc文件(字节码文件),如果有,并且修改时间比b.py晚,就直接调用b.pyc 否则编译b.py生成b.pyc,然后加载新生成的字节码文件 字节码对象