1、Node模块机制
1.1 请介绍一下node里的模块是什么
Node中,每个文件模块都是一个对象,它的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
function Module(id, parent) {
this .id = id; this .exports = {}; this .parent = parent; this .filename = null ; this .loaded = false ; this .children = []; } module.exports = Module; var module = new Module(filename, parent); |
所有的模块都是 Module 的实例。可以看到,当前模块(module.js)也是 Module 的一个实例。
1.2 请介绍一下require的模块加载机制
这道题基本上就可以了解到面试者对Node模块机制的了解程度基本上面试提到
1、先计算模块路径
2、如果模块在缓存里面,取出缓存
3、加载模块
4、的输出模块的exports属性即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// require 其实内部调用 Module._load 方法 Module._load = function (request, parent, isMain) {
// 计算绝对路径 var filename = Module._resolveFilename(request, parent); // 第一步:如果有缓存,取出缓存 var cachedModule = Module._cache[filename]; if (cachedModule) {
return cachedModule.exports; // 第二步:是否为内置模块 if (NativeModule.exists(filename)) {
return NativeModule.require(filename); } /********************************这里注意了**************************/ // 第三步:生成模块实例,存入缓存 // 这里的Module就是我们上面的1.1定义的Module var module = new Module(filename, parent); Module._cache[filename] = module; /********************************这里注意了**************************/ // 第四步:加载模块 // 下面的module.load实际上是Module原型上有一个方法叫Module.prototype.load try {
module.load(filename); hadException = false ; } finally {
if (hadException) {
delete Module._cache[filename]; } } // 第五步:输出模块的exports属性 return module.exports; }; |
接着上一题继续发问
1.3 加载模块时,为什么每个模块都有__dirname,__filename属性呢,new Module的时候我们看到1.1部分没有这两个属性的,那么这两个属性是从哪里来的
1 2 3 4 5 6 7 8 9 10 11 |
// 上面(1.2部分)的第四步module.load(filename) // 这一步,module模块相当于被包装了,包装形式如下 // 加载js模块,相当于下面的代码(加载node模块和json模块逻辑不一样) ( function (exports, require, module, __filename, __dirname) {
// 模块源码 // 假如模块代码如下 var math = require( 'math' ); exports.area = function (radius){
return Math.PI * radius * radius } }); |
也就是说,每个module里面都会传入__filename, __dirname参数,这两个参数并不是module本身就有的,是外界传入的
1.4 我们知道node导出模块有两种方式,一种是exports.xxx=xxx和Module.exports={}有什么区别吗
- exports其实就是module.exports
- 其实1.3问题的代码已经说明问题了,接着我引用廖雪峰大神的讲解,希望能讲的更清楚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
module.exports vs exports 很多时候,你会看到,在Node环境中,有两种方法可以在一个模块中输出变量: 方法一:对module.exports赋值: // hello.js function hello() {
console.log( 'Hello, world!' ); } function greet(name) {
console.log( 'Hello, ' + name + '!' ); } module.exports = {
hello: hello, greet: greet }; 方法二:直接使用exports: // hello.js function hello() {
console.log( 'Hello, world!' ); } function greet(name) {
console.log( 'Hello, ' + name + '!'
|