《深入浅出Node.js》读书笔记 - 模块机制

197 阅读2分钟

1. CommonJS模块规范

// add.js
exports.add = function() {
    return Array.from(arguments).reduce((pre,cur) => pre+cur,0)
}

// main.js
const { add } = require('./add')
let res = add(1,2,3)
console.log(res) // 6

通过require导入其他模块 通过exports导出本模块的方法

2. 对引入过对模块都会进行缓存,即所有模块在执行过程中只初始化一次。

// add.js
let i = 1
exports.add = function() {
  return i++
}

// main.js
var a1 = require('./add')
var a2 = require('./add')

console.log(a1.add()) // 1
console.log(a1.add()) // 2
console.log(a2.add()) // 3

3. 对于nodejs来说,每一个文件就是一个模块,每一个模块都有require, exports, module, __filename, __dirname这五个预先定义好都变量提供使用。

为什么能调用这个五个变量?

在对js文件编译的过程中,node对js对文件进行了头尾包装,加入了

function(require,exports,module, __filename,__dirname) {
 // js文件内容    
}

从而保证了作用域隔离,不用担心变量污染,最后将五个参数传递给这个function执行。执行之后返回exports属性给调用方。

4. exports 和 module.exports的使用以及区别

module
require
exports
如上图,module是一个对象, require和exports都是module的属性。

exports 和 module.export 指向同一个引用

  1. module.exports 初始值为一个空对象 {}
  2. exports 是指向的 module.exports 的引用 即 exports = module.exports
  3. require() 返回的是 module.exports 而不是 exports

所以如果我们exports = function(){}, module.export仍然为空对象{},别的文件也没有办法通过require调用到该函数

5. 模块分类

  1. node自身提供的核心模块,如 http、fs
  • 加载速度快。核心模块在node源代码编译中就编译成了二进制文件。node进程启动时,部分核心模块就加载到了内存中,所以引入核心模块时无需定位文件和编译执行。
  • 核心模块中有部分全为C/C++编写,另一部分核心模块为C/C++编写,javascript包装导出,在性能与开发门槛之间取一个平衡。全为C/C++编写的为内建模块,一般情况下开发者无需接触内建模块,因为核心模块中基本都封装了内建模块。
  1. 开发者编写的文件模块

文件模块时运行时加载,需要路径分析,文件定位,编译执行,所以加载速度较核心模块速度慢。

6. 拓展模块

可以使用C/C++ 拓展模块,提供Api供核心模块和文件模块调用。此处先跳过。等具备一定的C/C++开发能力再来学习。

7. 其他模块规范

除了CommonJS以外,还有AMD、CMD、ES6 Module

nodejs目前已经支持es6 module的写法,但需要添加 --experimental-modules标志位。