NodeJS中require,module,exports的关系
前言
作为NodeJS的开发人员,想必都知道NodeJS主要通过require,exports这两个关键字将代码中的各个模块组合到一起。其中具体的机制,之前也大致看过,但是一直没有完整的整理过一遍。本文就从运行一个NodeJS脚本开始,把NodeJS加载脚本的过程梳理一遍,算是当作自己的笔记吧。
记录
准备
我这边的NodeJS版本是
1 | $ node -v |
编写一个test.js文件。是的,里面就写这一句话。
1 | require() |
执行
1 | $ node test.js |
堆栈解析
这里出错的堆栈信息还是蛮有意思的,我把主要的代码都罗列了下。
1 | // NodeJS通过startup方法初始化,然后进入了Module的runMain方法 |
NodeJS的包裹层!
通过这个包裹层,我们原先的test.js文件就会变为下面这个样子。这也就是在我们写代码的时候,可以直接调用exports,require,module…的原因。
1 | (function(exports, require, module, filename, dirname)){ |
- module
test.js会被解析为一个module。 - exports
就是这个module上的一个属性。 - require
调用require方法,最终调用的就是Module._load方法1
2
3
4
5Module.prototype.require = function(path) {
assert(path, 'missing path');
assert(typeof path === 'string', 'path must be a string');
return Module._load(path, this);
};
最终的那个异常
在require方法中,NodeJS会对参数进行检查。这也就是当我们最终执行test.js时,出现错误“AssertionError: missing path”的原因所在。
小结
所有加载完成的模块,都会缓存在require.cache上。当我们执行require操作的时候,NodeJS会先从缓存里面找,如果不存在,就会去找对应的文件进行编译。
这一个特性可以让我们做不少有趣的事情,比如:
- 文件实时编译。
通过检测文件的改动,在发生改动时,清除require.cache缓存,对其进行重新加载编译。 - 动态的往exports上添加方法、属性。
因为exports是module对象上的属性,而module对象又是被缓存在require.cache上,所以也可以这样写。1
2
3exports.addMethod = function(methodName , method){
exports[methodName] = method
}
转载本站文章请注明作者(xtutu)和出处 xtutu