requiregitlabmuduleobjectificationrequire最终会将每个模块转化为对象functionModule(id,parent){this.id=id;this.exports={};this.parent=parent;updateChildren(父母,这个,假);this.filename=null;this.loaded=false;this.children=[];}require方法使用assert断言输入的有效性并调用_load方法。还有一个模块调用_load.runMain=function(){//加载主模块——命令行参数。Module._load(process.argv[1],null,true);//处理在程序进程的第一个tick中添加的任何nextTicks._tickCallback();};这个我不是特别确定,但是我基本确定是nodexxx.js命令调用的load方法。这里有很多关于处理main的东西,核心部分是if(isMain){process.mainModule=module;module.id='.';}这证明了上面的说法,runMain是为nodexxx.js命令调用的。另外,主模块的id必须是'.',parent必须为空。此外,它会在调用前检查模块缓存是否存在。为了简化删除主模块的处理,下面的代码创建了一个没有原型的空对象Module._cache=Object.create(null);Module._pathCache=Object.create(null);Module._load=function(request,parent,isMain){if(parent){debug('Module._loadREQUEST%sparent:%s',request,parent.id);}varfilename=Module._resolveFilename(request,parent,isMain);//缓存中是否存在varcachedModule=Module._cache[filename];如果(cachedModule){updateChildren(parent,cachedModule,true);返回cachedModule.exports;}//是否是原生模块if(NativeModule.nonInternalExists(filename)){debug('loadnativemodule%s',request);返回NativeModule.require(文件名);}//其他模块处理varmodule=newModule(filename,parent);Module._cache[文件名]=模块;tryModuleLoad(模块,文件名);返回module.exports;};这部分说明加载一个模块首先是判断模块名,然后是找缓存,找到native模块,然后是其他模块。最后一个return是最关键的,返回值永远是模块的exportsfornode_modulesfolderlookupRulesModule._nodeModulePaths=function(from){//保证'from'是绝对的.from=path.resolve(从);//尽早返回不仅是为了避免不必要的工作,也是为了*避免*返回//根的两个项目的数组:['//node_modules','/node_modules']if(from==='/')返回['/node_modules'];//注意:此方法*仅*在保证路径为绝对路径时有效。做一个在Windows和Posix上都适用的完全边缘大小写正确的path.split//是非常重要的。常量路径=[];变量p=0;变种最后=从。长度;for(vari=from.length-1;i>=0;--i){constcode=from.charCodeAt(i);if(code===47//*/*/){if(p!==nmLen)paths.push(from.slice(0,last)+'/node_modules');最后=我;p=0;}elseif(p!==-1){if(nmChars[p]===代码){++p;}否则{p=-1;从from开始,逐层查找node_modules文件夹Module._extensionsjs,json,node,mjs每个后缀文件都有对应的打开方式js清除可能的BOM头并加载jsonjsonParsenode.node这是一个用C/C++编写的扩展文件。通过dlopen()方法加载最终编译好的文件,可以看成是系统调用findPath。这部分代码比较多,随便看一个评论。//给定模块名称和要测试的路径列表,返回以下优先级中的第一个//匹配文件。////require("a.
