Node.js模块化的理解
Node.js 采用的是 CommonJs 规范,在 NodeJS 中,一般将代码合理拆分到不同的 JS 文件中,每一个文件就是一个模块,而文件路径就是模块名。 在编写每个模块时,都有 require、exports、module 三个预先定义好的变量可供使用。
Node.js 中模块的分类:
- 核心模块(已经封装好的内置模块);
- 自己定义的模块;
- 第三方的模块(npm 下载下来的);
require
require
函数用来在一个模块中引入另外一个模块。传入一个模块名,返回一个模块导出对象。用法:let cc = require("模块名")
,其中模块名可以用绝对路径也可以用相对路径,模块的后缀名.js 可以省略。例如:
1 | let cc1 = require('./main.js') |
require()函数用两个作用:
- 执行导入的模块中的代码;
- 返回导入模块中的接口对象;
exports
exports
对象用来导出当前模块的公共方法或属性,别的模块通过require
函数使用当前模块时得到的就是当前模块的exports
对象。用法:exports.name
,name 为导出的对象名。例子:
1 | exports.add = function () { |
其实 exports 类似于 ES6 中的 export 的用法,用来导出一个指定名字的对象。
module.exports
module.exports
用来导出一个默认对象,没有指定对象名,常见于修改模块的原始导出对象。比如原本模块导出的是一个对象,我们可以通过 module.exports 修改为导出一个函数。如下:
1 | module.exports = function () { |
模块的初始化
一个模块中的 JS 代码仅在模块第一次被使用时执行一次,并且在使用的过程中进行初始化,之后缓存起来便于后续继续使用。
主模块
通过命令行参数传递给 NodeJS 以启动程序的模块被称为主模块。主模块负责调度组成整个程序的其它模块完成工作。例如通过以下命令启动程序时,main.js 就是主模块。
1 | $ node main.js // 运行main.js启动程序,main.js称为主模块 |
完整实例:
在项目中我们有个hello.js
文件,里面定义了一个求和的函数
1 | var a = 1 |
我们在项目的主模块 main.js
中引入hello.js
1 | var add1 = require('./hello') |
该程序运行的结果如下:
1 | $ node main.js |
我们可以看到hello.js
并没有别引入两次而初始化两次,说明模块只会在执行的过程中被初始化一次。
module.exports 和 exports 的区别
Node 中,每个模块都有一个exports
接口对象,我们需要把公共的方法或者字符串挂载在这个接口对象中,其他的模块才可以使用。
Node.js 中只有模块作用域,默认两个模块之间的变量,方法互不冲突,互不影响,这样就导致一个问题,我们怎样使用加载进来的模块中的方法呢?这就需要在另外一个模块
exports
接口对象中挂载模块中公共的方法。
exports
我们在a.js
中有以下代码:
1 | let foo = 'hello' |
此时,在b.js
中如果需要使用add
方法,只需引入a.js
即可。b.js
代码如下:
1 | let a = require('./a.js') // a.js和b.js在同级目录下,注意:同级目录必须加“./” |
相反,如果我们没有在a.js
exports 接口对象中挂载 add 方法,那么这里就得不到结果。
module.exports
对于上面的例子,我们同样可以利用module.exports
来写,只需把暴露的方式改成如下:
1 | module.exports.add = add |
1 | // 也可以用对象的方式 |
总结
- Node 中每个模块都有一个
module
对象,module
对象中的有一个exports
属性为一个接口对象,我们需要把模块之间公共的方法或属性挂载在这个接口对象中,方便其他的模块使用这些公共的方法或属性。 - Node 中每个模块的最后,都会
return: module.exports
。 - Node 中每个模块都会把
module.exports
指向的对象赋值给一个变量exports
,也就是说:exports = module.exports
。 module.exports = XXX
,表示当前模块导出一个单一成员,结果就是 XXX。- 如果需要导出多个成员时必须使用
exports.add = XXX; exports.foo = XXX;
或者使用module.exports.add = XXX; module.export.foo = XXX;
。