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
如上图,module是一个对象, require和exports都是module的属性。
require
exports
exports 和 module.export 指向同一个引用
- module.exports 初始值为一个空对象 {}
- exports 是指向的 module.exports 的引用 即 exports = module.exports
- require() 返回的是 module.exports 而不是 exports
所以如果我们exports = function(){}, module.export仍然为空对象{},别的文件也没有办法通过require调用到该函数
5. 模块分类
- node自身提供的核心模块,如 http、fs
- 加载速度快。核心模块在node源代码编译中就编译成了二进制文件。node进程启动时,部分核心模块就加载到了内存中,所以引入核心模块时无需定位文件和编译执行。
- 核心模块中有部分全为C/C++编写,另一部分核心模块为C/C++编写,javascript包装导出,在性能与开发门槛之间取一个平衡。全为C/C++编写的为内建模块,一般情况下开发者无需接触内建模块,因为核心模块中基本都封装了内建模块。
- 开发者编写的文件模块
文件模块时运行时加载,需要路径分析,文件定位,编译执行,所以加载速度较核心模块速度慢。
6. 拓展模块
可以使用C/C++ 拓展模块,提供Api供核心模块和文件模块调用。此处先跳过。等具备一定的C/C++开发能力再来学习。
7. 其他模块规范
除了CommonJS以外,还有AMD、CMD、ES6 Module
nodejs目前已经支持es6 module的写法,但需要添加 --experimental-modules标志位。